路過proxy的socket
主題:用socket在做網路的溝通,中間想透過proxy server該怎麼辦???
簡單來說就下面這幾步,其中跟一般建connection不同的就只有第二步,要先做handshaking
0.建socket
1.跟proxy建立connection
2.丟Sock4/Sock5的protocol給proxy
3.之後丟message都透過這個socket
簡單的code來解釋
0. int Socket = socket( AF_INET, SOCK_STREAM, 0 );
1. connect(Socket, <struct sockaddr with proxy info>, sizeof(struct sockaddr));
2. a. send(Socket, <protocol packet>, <packet size>, 0);
b. recv(Socket, <reply packet>, <reply packet size>);
c. // check the 2nd byte of the reply packet
3. send(Socket, <a buffer with your message>, <message length>, 0);
重點就是在第2步啦!
接下來,看看Sock4/Sock5所需準備的packet format
SOCK4:
Request Format:
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
# of bytes: 1 1 2 4 variable 1
packet[0] = 4; // version
packet[1] = 1; // connection
packet[2] = htons(port); // port
packet[4] = inet_addr(host_name); // ip
packet[8] = 0; // NULL terminator
Reply Format:
+----+----+----+----+----+----+----+----+
| VN | CD | DSTPORT | DSTIP |
+----+----+----+----+----+----+----+----+
# of bytes: 1 1 2 4
VN: reply code, should be 0
CD: result code, as following,
90: request granted
91: request rejected or failed
92: request rejected because SOCKS server cannot connect to identd on the client
93: request rejected because the client program and identd report different user-ids
SOCK5:
這邊填的值略有不同
packet[0] = 5; // version
packet[1] = 2; // 有幾個method
packet[2] = 0; // 第一個method, 0:不需驗證
packet[3] = 2; // 第二個method, 2:要驗證
Reply Format:
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
VER: version, should be '5'
REP: reply code, 0:不需驗證, 2:要驗證, others:failed
接下來程序比較複雜,需要多送一次authentication跟建connection
SEND: Authentication Request Format:
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
packet[0] = 1; // i don't know why...authentication version??
packet[1] = strlen(username);
memcpy(packet+2, username, strlen(username)));
packet[2 + strlen(username)] = strlen(password);
memcpy(packet + strlen(username) + 3, password, strlen(password)));
REPLY:
驗證成功:
reply[0] == 1 && // version we sent
reply[1] == 0 // reply code, always should be 0
SEND: Ask For Connection:
packet[0] = 5; // version
packet[1] = 1; // connection request
packet[2] = 0; // reserved, must be 0
packet[3] = 1; // IPv4 = 1
packet[4] = inet_addr(host_name); // the server host name
packet[8] = htons(port); // the server port
REPLY:
connection結果:
reply[0] == 5 && // version we sent
reply[1] == 0 // reply code, always should be 0
ref:
http://blog.csdn.net/bodybo/article/details/7274865
http://www.cppblog.com/zuhd/archive/2010/06/08/117366.html
http://www.opensource.apple.com/source/curl/curl-42/curl/lib/socks.c
留言
張貼留言