-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathserver.cpp
289 lines (263 loc) · 9.21 KB
/
server.cpp
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#include <event2/util.h>
#include <event2/dns.h>
#include "server.h"
#include "cipher.h"
#include "socks5.h"
#define ENCRYPT
#ifdef _WIN32
#pragma comment(lib, "ws2_32.lib")
#endif
void server::local_event_cb(bufferevent *bev, short what, void *ctx) {
spdlog::debug("local event_cb(what)-->: {0:x} ", what);
auto context = static_cast<Socks5ctx *>(ctx);
if (!context) {
spdlog::warn("with no context in local_event...");
return;
}
//读到文件结尾或者发生错误
if (what & BEV_EVENT_TIMEOUT) {
spdlog::debug("本地操作时发生错误");
if (context->partner) {
bufferevent_free(context->partner);
context->partner = nullptr;
}
bufferevent_free(context->self);
context->self = nullptr;
delete context;
context = nullptr;
}
if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
if (what & BEV_EVENT_ERROR) {
spdlog::debug("local error!");
}
if (context->partner) {
bufferevent_free(context->partner);
context->partner = nullptr;
}
bufferevent_free(context->self);
context->self = nullptr;
delete context;
context = nullptr;
}
}
void server::local_read_cb(bufferevent *bev, void *arg) {
auto context = static_cast<Socks5ctx *>(arg);
if (!context) {
spdlog::warn("没有context了local_read_cb...");
return;
}
socks5::handle_first(bev, context);
}
void server::remote_event_cb(bufferevent *bev, short what, void *ctx) {
//bug fixed
spdlog::debug("remote event_cb(what)-->: {0:x} ", what);
auto context = static_cast<Socks5ctx *>(ctx);
if (!context) {
spdlog::warn("没有context了 remote_event...");
return;
}
if (what & BEV_EVENT_CONNECTED) {
spdlog::debug("remote server tcp handshake successful...");
// bug: 这个时候有可能已经没有Local的context了
if (!context->self) {
spdlog::warn("with no local context...");
return;
}
unsigned char reply[7] = {0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00};
#ifdef ENCRYPT
Cipher::encrypt_byte(reply, sizeof(reply));
#endif
//返回握手包
bufferevent_write(context->self, reply, sizeof(reply));
return;
}
if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
if (what & BEV_EVENT_ERROR) {
spdlog::debug("remote server error...");
}
if (context->self) {
bufferevent_free(context->self);
context->self = nullptr;
}
bufferevent_free(context->partner);
context->partner = nullptr;
delete context;
context = nullptr;
} else {
if (what & BEV_EVENT_TIMEOUT) {
spdlog::debug("remote server read data timeout...");
if (context->self) {
std::cout << "context:" << context->self << std::endl;
bufferevent_free(context->self);
context->self = nullptr;
}
bufferevent_free(bev);
context->partner = nullptr;
delete context;
context = nullptr;
}
}
}
void server::remote_read_cb(bufferevent *bev, void *arg) {
auto context = static_cast<Socks5ctx *>(arg);
if (!context) {
spdlog::warn("with no context in remote_read_cb...");
return;
}
if (!context->self) {
evbuffer *remote;
//获取服务端的evbuffer
remote = bufferevent_get_input(context->partner);
auto len = evbuffer_get_length(remote);
//把数据从缓冲区移除
evbuffer_drain(remote, len);
}
#ifdef ENCRYPT
Cipher::encrypt(context->self, context->partner);
#else
evbuffer *src,*dst;
src = bufferevent_get_input(context->partner);
dst = bufferevent_get_output(context->self);
evbuffer_add_buffer(dst, src);
#endif
}
void server::listen_cb(evconnlistener *lev, evutil_socket_t s, sockaddr *sin, int sin_len, void *arg) {
char ip[128]{0};
auto r_sa = (sockaddr_in *) sin;
evutil_inet_ntop(r_sa->sin_family, &(r_sa->sin_addr.s_addr), ip, sin_len);
spdlog::info("New connection from {}:{}", ip, r_sa->sin_port);
auto base = evconnlistener_get_base(lev);
//监听本地客户端,用本地客户端连接的socket
auto bufev_local = bufferevent_socket_new(base, s, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
//本地客户端超时为15s(BUG)
timeval local_time_out = {0, 0};
bufferevent_set_timeouts(bufev_local, &local_time_out, 0);
//----------------------------------------------------------------------//
//设置上下文
Socks5ctx *socks5Ctx = new Socks5ctx();
//初始化参数
socks5Ctx->self = bufev_local;
//设置回调和事件
bufferevent_setcb(bufev_local, local_read_cb, nullptr, local_event_cb, socks5Ctx);
bufferevent_enable(bufev_local, EV_READ | EV_WRITE);
}
void server::setConfig(unsigned short listen_port, std::string password) {
server::listen_port = listen_port;
std::string decoded = base64_decode(password);
auto t = reinterpret_cast<const unsigned char *>(decoded.c_str());
for (auto i = 0; i < decoded.length(); i++) {
Cipher::password[i] = (int) t[i];
}
}
void server::run() {
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
auto err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
spdlog::warn("WSAStart启动失败");
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
spdlog::warn("找不到可用的 Winsock.dll");
WSACleanup();
} else {
spdlog::info("Winsock 2.2 dll 加载成功");
}
#else
// 无视管道信号,发送数据给已关闭的socket
if (std::signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
}
#endif // _WIN32
auto base = event_base_new();
if (base) {
base_loop = base;
// evdns_base_config_windows_nameservers()
auto dns_base = evdns_base_new(base, 1);
base_dns_loop = dns_base;
} else { exit(0); }
//绑定地址
sockaddr_in sin_local{};
memset(&sin_local, 0, sizeof(sin_local));
sin_local.sin_family = AF_INET;
sin_local.sin_port = htons(listen_port);
//监听端口,接收tcp流量
auto ev_listen = evconnlistener_new_bind(
base,
listen_cb,
base,
LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, //自动变为non-block
16,
(sockaddr *) &sin_local,
sizeof(sin_local));
if (ev_listen) {
spdlog::info("Listen on: [::]:{}", listen_port);
//资源清理
event_base_dispatch(base_loop);
evconnlistener_free(ev_listen);
event_base_free(base_loop);
} else {
event_base_free(base_loop);
spdlog::warn("Listen port [{}] error!", listen_port);
}
}
void server::clear() {
#ifdef _WIN32
WSACleanup();
#endif
}
event_base *server::base_loop = nullptr;
evdns_base *server::base_dns_loop = nullptr;
unsigned short server::listen_port = 7009;
void server::dns_cb(int errcode, evutil_addrinfo *answer, void *ctx) {
auto context = static_cast<Socks5ctx *>(ctx);
if (!context) {
spdlog::warn("dns_cb error!");
return;
}
if (errcode) {
spdlog::info("dns解析出错....");
spdlog::warn("%s", evutil_gai_strerror(errcode));
} else {
char temp_ip[128] = {0};
auto sin = (sockaddr_in *) answer->ai_addr;
auto ip = evutil_inet_ntop(answer->ai_family, &sin->sin_addr, temp_ip, sizeof(temp_ip));
//可能解析不成功
if (!ip) {
spdlog::warn("ip resolve error!");
exit(0);
}
// std::string real_ip = temp_ip;
// context->request_ip = real_ip;
std::cout << ip << std::endl;
context->request_ip = std::string(temp_ip);
spdlog::debug("Ip:{}-->port:{}", context->request_ip, context->request_port);
//解析dns完成,连接远程服务器
auto bufev_remote = bufferevent_socket_new(base_loop, -1, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
sockaddr_in sin_remote{};
memset(&sin_remote, 0, sizeof(sin_remote));
sin_remote.sin_family = AF_INET;
sin_remote.sin_port = htons(context->request_port);
const char *src = context->request_ip.c_str();
evutil_inet_pton(AF_INET, src, &sin_remote.sin_addr.s_addr);
spdlog::debug("建立tcp的ip:{} port:{}", src, context->request_port);
//服务端服务器超时时间为15s
timeval t1 = {15, 0};
bufferevent_set_timeouts(bufev_remote, &t1, nullptr); //读取 写入
//设置回调
bufferevent_setcb(bufev_remote, remote_read_cb, nullptr, remote_event_cb, context);
bufferevent_enable(bufev_remote, EV_READ | EV_WRITE);
//连接服务端
auto re = bufferevent_socket_connect(
bufev_remote,
(sockaddr *) &sin_remote,
sizeof(sin_remote));
if (re == 0) {
context->partner = bufev_remote;
} else {
spdlog::warn("connect事件失败");
return;
evutil_freeaddrinfo(answer);
}
}
}