C++使用Socks5协议进行代理上网(三)

上一篇文章连接:https://blog.csdn.net/hu421160052/article/details/88870940

这里是账号密码认证之后,这里需要你提供你要到达的具体的目的server的IP和Port,以及连接的具体方式

	index = 0;
	byte Msg3[100];

	//socks5协议部分(5.客户端认证成功后开始进行请求)
	//|-------|-------|-------|--------|-----------|------------| 
	//|  VER  |  CMD  |  RSV  |  ATYP  |  DST.ADDR |  DST.ADDR  |
	//|-------|-------|-------|--------|-----------|------------|
	//|   1	  |	  1   |  0x00 |    1   |   Active  |      2     |
	//|-------|-------|-------|--------|-----------|------------|
	//  VER.是SOCKS协议版本,这里应该是0x05.
	//	CMD.是SOCKS的命令码:
	//		0x01:表示CONNECT请求
	//		0x02:表示BIND请求
	//		0x03:表示UDP转发
	//  RSV.0x00:保留,无实际作用
	//  ATYP.DST.ADDR类型:
	//		0x01:表示IPV4地址
	//		0x03:表示域名格式
	//		0x04:表示IPV6地址
	//  DST.ADDR.目的地址
	//		当ATYP=0x01 DST.ADDR部分为四字节长度,内容为IP本身
	//		当ATYP=0x03 第一个部分为一个1字节表示域名长度,第二部分就是剩余内容为具体域名。Active表示长度不定。没有\0作为结尾
	//	DST.PORT 网络字节序表示的目的端口

	Msg3[index++] = 0x05;						//Version 版本号5
	Msg3[index++] = 0x01;						//CMD CONNECT请求
	Msg3[index++] = 0x00;						//Reserve = 0x00 must be ;
	Msg3[index++] = 0x01;						//ATYP=IPV4
	int ads1 = atoi(ByteAddress[0]);
	int ads2 = atoi(ByteAddress[1]);
	int ads3 = atoi(ByteAddress[2]);
	int ads4 = atoi(ByteAddress[3]);
	
	Msg3[index++] = (byte)(0xff & ads1);
	Msg3[index++] = (byte)(0xff & ads2);
	Msg3[index++] = (byte)(0xff & ads3);
	Msg3[index++] = (byte)(0xff & ads4);

	Msg3[index++] = (byte)(dest_port / 256);	//Port
	Msg3[index++] = (byte)(dest_port % 256);

	sprintf(result, "VER:0x%d%d\r\n CMD:0x%d%d\r\n RSV:0x%d%d\r\n ATYP:0x%d%d\r\n IP1:0x%d%d\r\n IP2:0x%d%d\r\n IP3:0x%d%d\r\n IP4:0x%d%d\r\n Port1:0x%d%d\r\n Port2:0x%d%d\r\n", Msg3[0]/16, Msg3[0] % 16, Msg3[1]/16,Msg3[1] % 16, Msg3[2]/16, Msg3[2] % 16,Msg3[3] / 16, Msg3[3] % 16, Msg3[4] / 16, Msg3[4] % 16, Msg3[5] / 16, Msg3[5] % 16, Msg3[6] / 16, Msg3[6] % 16, Msg3[7] / 16, Msg3[7] % 16, Msg3[8] / 16, Msg3[8] % 16, Msg3[9] / 16, Msg3[9] % 16);
	MessageBoxA(NULL, result, "第三次发送数据:", NULL);//第一次认证,如果为1则正确,为0则错误
	send(sockClient, (char*)Msg3, index, 0);
	
	//socks5协议部分(6.代理服务器->客户端,确认连接)
	//|-------|-------|-------|--------|-----------|------------| 
	//|  VER  |  RCV  |  RSV  |  ATYP  |  DST.ADDR |  DST.ADDR  |
	//|-------|-------|-------|--------|-----------|------------|
	//|   1	  |	  1   |  0x00 |    1   |   Active  |      2     |
	//|-------|-------|-------|--------|-----------|------------|
	//  VER.返回必须为0x05.
	//	RCV.返回的状态码:
	//		0x00:succeeded
	//		0x01:general SOCKS server failure
	//		0x02:connection not allowed by ruleset
	//		0x03:Network unreachable
	//		0x04:Host unreachable
	//		0x05:Connection refused
	//		0x06:TTL expired
	//		0x07:Command not supported
	//		0x08: Address type not supported
	//		0x09:to X’FF’ unassigned
	//  RSV.0x00:保留,无实际作用
	//  ATYP.仅用于响应BIND命令:
	//		0x01:表示IPV4地址
	//		0x03:表示域名格式
	//		0x04:表示IPV6地址
	//  DST.ADDR.目的地址,仅用于响应BIND命令
	//		当ATYP=0x01 DST.ADDR部分为四字节长度,内容为IP本身
	//		当ATYP=0x03 第一个部分为一个1字节表示域名长度,第二部分就是剩余内容为具体域名。Active表示长度不定。没有\0作为结尾
	//	DST.PORT 网络字节序表示的目的端口,仅用于响应客户端BIND命令
	
	byte RecvMsg3[100];
	numl=recv(sockClient, (char*)RecvMsg3, sizeof((char*)RecvMsg3), 0);
	int t00 = (RecvMsg3[0] / 16), t01 = (RecvMsg3[0] % 16);
	int t10 = (RecvMsg3[1] / 16), t11 = (RecvMsg3[1] % 16);
	int t20 = (RecvMsg3[2] / 16), t21 = (RecvMsg3[2] % 16);
	int t30 = (RecvMsg3[3] / 16), t31 = (RecvMsg3[3] % 16);
	int t40 = (RecvMsg3[4] / 16), t41 = (RecvMsg3[4] % 16); 
	int t50 = (RecvMsg3[5] / 16), t51 = (RecvMsg3[5] % 16);
	int t60 = (RecvMsg3[6] / 16), t61 = (RecvMsg3[6] % 16);
	int t70 = (RecvMsg3[7] / 16), t71 = (RecvMsg3[7] % 16);
	int t80 = (RecvMsg3[8] / 16), t81 = (RecvMsg3[8] % 16);
	int t90 = (RecvMsg3[9] / 16), t91 = (RecvMsg3[9] % 16);

	sprintf(result, "Length:%d \r\n VER:0x%d%d\r\n RCV:0x%d%d\r\n RSV:0x%d%d\r\n ATYP:0x%d%d\r\n IP1:0x%d%d\r\n IP2:0x%d%d\r\n IP3:0x%d%d\r\n IP4:0x%d%d\r\n Port1:0x%d%d\r\n Port2:0x%d%d\r\n", numl,t00, t01, t10, t11,t20,t21,t30,t31,t40,t41,t50,t51,t60,t61,t70,t71,t80,t81, t90, t91);
	MessageBoxA(NULL, result, "第三次返回结果:", NULL);//第一次认证,如果为1则正确,为0则错误

发送数据和服务器返回结果:
在这里插入图片描述

在这里插入图片描述
最后主要注意RCV的值,为0时表示验证成功,可以继续下一步,在这里也有些常见的错误我贴出来一下
1.账号密码错误
在这里插入图片描述
RCV返回值为2
看协议
0x02:connection not allowed by ruleset
意思大概就是,你虽然连接上了,但是规则不允许帮你后续转发消息。所以代理失败

2.超时及网络错误:
在这里插入图片描述
在这里插入图片描述
这里第一种主要注意返回值的长度Length为-1,这里说明在你请求数据的时候,服务器已经单方面关闭了socket,接受不到任何信息,我是这样理解的。
第二种RCV返回1
0x01:general SOCKS server failure
这个就是失败,反正我测试情况下,网络状态不好和超时,就会报错,超时时间大概就是10s左右。

好了,说回来,如果返回值正常,就可以继续最后一步,数据转发。
第四部分:
https://blog.csdn.net/hu421160052/article/details/88871757

猜你喜欢

转载自blog.csdn.net/hu421160052/article/details/88871480