如何向socks5代理服务器添加身份验证?

时间:2011-05-19 05:15:01

标签: c++ sockets authentication proxy winsock

我正在尝试使用我发现谷歌搜索和自定义代码来构建socks5代理服务器。到目前为止一切正常但现在我想为socks5添加身份验证。

这是处理请求的代码:

SOCKET socks5Handler( SOCKET Client, char* Buffer )
{
    SOCKS5AUTH sAuth;
    char   *Host    = NULL;
    SOCKET  Target  = INVALID_SOCKET;
    ulong   Ip      = 0;
    ushort  Port    = 0;
    byte    Command = 0,
            Type    = 0;
    int     i       = 0;
    if( sockRecv(Client, Buffer, 1) < 0 )
        return INVALID_SOCKET;
    if( sockRecv(Client, Buffer, Buffer[0]) < 0 )
        return INVALID_SOCKET;
    Buffer[0] = 0x05;
    Buffer[1] = 0x00;
    send( Client, Buffer, 2, 0 );
    if( sockRecv(Client, Buffer, 4) < 0 )
        return INVALID_SOCKET;
    Command  = Buffer[1];
    Type     = Buffer[3];
    if( Type == 0x01 ) {
        if( sockRecv(Client, Buffer, 4) < 0 )
            return INVALID_SOCKET;
        Ip = *((ulong*)Buffer);
    } else if( Type == 0x03 ) {
        if( sockRecv(Client, Buffer, 1) < 0 )
            return INVALID_SOCKET;
        i = Buffer[0];
        if( sockRecv(Client, Buffer, i) < 0 )
            return INVALID_SOCKET;
        Buffer[i] = 0;
        Host      = Buffer;
    } else
        return INVALID_SOCKET;
    if( sockRecv(Client, (char*)&Port, 2) < 0)
        return INVALID_SOCKET;
    if( Command == 0x01 ) {
        if( Host )
            Ip = sock_resolve( Host );
        Target = sock_connect( sock_create(), Ip, htons(Port) );
        if( Target == INVALID_SOCKET )
            return INVALID_SOCKET;
    } else
        return INVALID_SOCKET;
    Buffer[0] = 0x05;
    Buffer[1] = 0x00;
    Buffer[2] = 0x00;
    Buffer[3] = 0x01;
    *((ulong* )(Buffer + 4)) = Ip;
    *((ushort*)(Buffer + 8)) = Port;
    send( Client, Buffer, 10, 0 );
    return Target;
}

BOOL sockRecv( SOCKET Sock, char* Buffer, int Length )
{
    int r = 0;
    while( Length )
    {
        r = recv( Sock, Buffer, Length, 0 );
        if( r <= 0 )
            return FALSE;
        Buffer += r;
        Length -= r;
    }
    return TRUE;
}

我发现如果我添加:

if(Buffer[0] != 0x02)
     return INVALID_SOCKET;

在第一个sockRecv之后,我可以知道是否正在发送auth(0x1不是auth,0x2是auth)。

现在,我如何阅读发送的用户名和密码?

我尝试嗅探网络,但这并没有向我显示任何好处。

1 个答案:

答案 0 :(得分:1)

SOCKS5协议在RFC 1928中定义。 0x02用户/密码身份验证方法在RFC 1929中定义。摘录:

   Once the SOCKS V5 server has started, and the client has selected the
   Username/Password Authentication protocol, the Username/Password
   subnegotiation begins.  This begins with the client producing a
   Username/Password request:

           +----+------+----------+------+----------+
           |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
           +----+------+----------+------+----------+
           | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
           +----+------+----------+------+----------+

   The VER field contains the current version of the subnegotiation,
   which is X'01'. The ULEN field contains the length of the UNAME field
   that follows. The UNAME field contains the username as known to the
   source operating system. The PLEN field contains the length of the
   PASSWD field that follows. The PASSWD field contains the password
   association with the given UNAME.

   The server verifies the supplied UNAME and PASSWD, and sends the
   following response:

                        +----+--------+
                        |VER | STATUS |
                        +----+--------+
                        | 1  |   1    |
                        +----+--------+

   A STATUS field of X'00' indicates success. If the server returns a
   `failure' (STATUS value other than X'00') status, it MUST close the
   connection.

实际上,这几乎是整个RFC的复制和粘贴。这很简单。

顺便说一句,“无认证”是方法0x00。方法0x01是GSSAPI(参见RFC 1961)。客户端可能支持多种身份验证方法。