我正在尝试使用我在谷歌搜索中发现的代码构建一个 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)。
现在,我如何读取发送的用户名和密码?
我尝试嗅探网络,但没有显示任何有用信息。
最佳答案
SOCKS5 协议(protocol)在 RFC 1928 中定义. RFC 1929 中定义了 0x02 用户/密码身份验证方法.摘录:
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)。客户端可能支持多种身份验证方法。
关于c++ - 如何向 socks5 代理服务器添加身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6054092/