1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#pragma once

#include <stdio.h>
#include <WinSock2.h>

////https://blog.csdn.net/educast/article/details/17450951

class CProxy_TestDlg
{
int HttpConnect(const char* proxy_ip, int proxy_port, const char* svr_ip, int svr_port);
int Socket5Connect(const char* proxy_ip, int proxy_port, const char* user, const char* passwd, const char* svr_ip, int svr_port);
};


//代理方式包括:HTTP代理、SOCKET5代理。RFC参考文档:http://oss.org.cn/man/develop/rfc/default.htm
//一、通过HTTP代理

int CProxy_TestDlg::HttpConnect(const char* proxy_ip, int proxy_port, const char* svr_ip, int svr_port)
{
SOCKET socket_ = ::socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sa;
sa.sin_addr.s_addr = inet_addr(proxy_ip);
sa.sin_port = htons(proxy_port);
sa.sin_family = AF_INET;

int error_code = ::connect(socket_, (SOCKADDR*)&sa, sizeof(sa));
if (error_code == SOCKET_ERROR)
{
::closesocket(socket_);
return 1;
}
char tmpBuffer[128] = { 0 };
::sprintf(tmpBuffer, "CONNECT %s:%d HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\nConnection: Keep-Alive\r\n\r\n", svr_ip, svr_port);
::send(socket_, tmpBuffer, strlen(tmpBuffer), 0);
memset(tmpBuffer, 0, 128);
::recv(socket_, tmpBuffer, 128, 0);
int mj, mi, code;
::sscanf(tmpBuffer, "HTTP/%d.%d %d", &mj, &mi, &code);
if (code != 200)
{
::closesocket(socket_);
return 2;
}
::closesocket(socket_);
return 0;
}

//HTTP代理方式测试通过。。。
//二、SOCKET5代理
//1、使用的结构如下:

#pragma pack(push,1)
//请求认证方式
typedef struct tagSocket5_Requst
{
char Ver; //版本号:05
char NMethods;
char Methods[255];
}Socket5_Request, * LPSocket5_Request;
//认证方式应答
typedef struct tagSocket5_Response
{
char Ver;
char Method;//X'00'不需要认证;X'01'GSSAPI;X'02用户名/密码;X'03' -- X'7F'由IANA分配;X'80' -- X'FE'为私人方法所保留的;X'FF'没有可以接受的方法

}Socket5_Response, * LPSocket5_Response;

//认证请求
typedef struct tagSocket5_Auth_Request
{
char Ver; //1
char Ulen;
char Name[255];
char PLen;
char Pass[255];
}Socket5_Auth_Request, * LPSocket5_Auth_Request;

typedef struct tagSocket5_Auth_Response
{
char Ver;
char Status;
}Socket5_Auth_Response, * LPSocket5_Auth_Response;
//连接请求
typedef struct tagSocket5_Connect_Request
{
char Ver;
char Cmd;//CONNECT:X'01';BIND:X'02';UDP ASSOCIATE:X'03'
char Rsv;//保留,填0
char Atyp;// 后面的地址类型,IPV4:X'01';域名:X'03';IPV6:X'04',暂时只支持IPV4
unsigned long DestAddr;//IPV4是4个字节,IPV6是6个字节;基于域名的地址,地址字段中的第一字节是以字节为单位的该域名的长度,没有结尾的NUL字
unsigned short DestPort;

}Sokcet5_Connect_Request, * LPSocket5_Connect_Request;
//连接应答
typedef struct tagSokcet5_Connect_Response
{
char Ver;
char Rep;
char Rsv;
char Atyp;
unsigned long DestAddr;
unsigned short DestPort;
}Socket5_Connect_Response, * LPSocket5_Connect_Response;
#pragma pack(pop)
//2、函数定义:
int CProxy_TestDlg::Socket5Connect(const char* proxy_ip, int proxy_port, const char* user, const char* passwd, const char* svr_ip, int svr_port)
{
//首先连接SOCKET5代理服务器
SOCKET socket_ = ::socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sa;
sa.sin_addr.s_addr = inet_addr(proxy_ip);
sa.sin_port = htons(proxy_port);
sa.sin_family = AF_INET;

int error_code = ::connect(socket_, (SOCKADDR*)&sa, sizeof(sa));
if (error_code == SOCKET_ERROR)
{
::closesocket(socket_);
return 1;
}
char buffer[128] = { 0 };
int len = 0;
//发送认证发送请求Socket5_Request/Socket5_Response
Socket5_Request req;
Socket5_Response rep;
req.Ver = 0x05;
req.NMethods = 2;
req.Methods[0] = 0;
req.Methods[1] = 2;
if ((len = ::send(socket_, (char*)&req, sizeof(req), 0)) <= 0)
{
::closesocket(socket_);
return 4;
}

if ((len = ::recv(socket_, (char*)&rep, sizeof(rep), 0)) <= 0)
{
::closesocket(socket_);
return 4;
}

if (rep.Ver != 0x05)
{
::closesocket(socket_);
return 5;
}

if (rep.Method != 0x00 && rep.Method != 0x02)
{
::closesocket(socket_);
return 6;
}

if (rep.Method == 0x02)
{//需要用户名、密码验证

//进行认证Socket5_Auth_Request/Socket5_Auth_Response
Socket5_Auth_Request auth_req;
Socket5_Auth_Response auth_rep;
memset(&auth_req, 0, sizeof(Socket5_Auth_Request));
memset(&auth_rep, 0, sizeof(Socket5_Auth_Response));
auth_req.Ver = 1;//?
auth_req.Ulen = strlen(user);
strcpy(auth_req.Name, user);
auth_req.PLen = strlen(passwd);
strcpy(auth_req.Pass, passwd);
if ((len = ::send(socket_, (char*)&auth_req, sizeof(auth_req), 0)) <= 0)
{
::closesocket(socket_);
return 4;
}
if ((len = ::recv(socket_, (char*)&auth_rep, sizeof(auth_rep), 0)) <= 0)
{
::closesocket(socket_);
return 4;
}
if (auth_rep.Status != 0)
{
::closesocket(socket_);
return 7;
}
}
//发送连接请求Sokcet5_Connect_Request/Socket5_Connect_Response
Sokcet5_Connect_Request conn_req;
Socket5_Connect_Response conn_rep;
memset(&conn_req, 0, sizeof(Sokcet5_Connect_Request));
memset(&conn_rep, 0, sizeof(Socket5_Connect_Response));

conn_req.Ver = 0x05;
conn_req.Cmd = 0x01;//
conn_req.Atyp = 0x01;
conn_req.DestAddr = inet_addr(svr_ip);
conn_req.DestPort = htons(svr_port);

if ((len = ::send(socket_, (char*)&conn_req, sizeof(conn_req), 0)) <= 0)
{
::closesocket(socket_);
return 4;
}

if ((len = ::recv(socket_, (char*)&conn_rep, sizeof(conn_rep), 0)) <= 0)
{
::closesocket(socket_);
return 4;
}
if (conn_rep.Rep != 0)
{
::closesocket(socket_);
return 8;
}
//连接成功

::closesocket(socket_);
return 0;
}

//SOCKET5还没有测试。。。
//三、根据网址获取该网址的IP地址

char* URL2IP(const char* url)
{
struct hostent* ph;
struct in_addr in;
memset(&in, 0x0, sizeof(in));
// 传递的域名地址通过 gethostbyname 函数转换成 HOSTENT 结构的指针
if ((ph = gethostbyname(url)) == NULL)
return NULL;

memcpy((char**)&in, ph->h_addr_list[0], sizeof(in));

return ::inet_ntoa(in);
}