diff options
-rw-r--r-- | src/gns/gnocksy/gnocksy.c | 228 | ||||
-rw-r--r-- | src/gns/gnocksy/protocol.h | 57 |
2 files changed, 175 insertions, 110 deletions
diff --git a/src/gns/gnocksy/gnocksy.c b/src/gns/gnocksy/gnocksy.c index a7b25e30c..3c5cb49eb 100644 --- a/src/gns/gnocksy/gnocksy.c +++ b/src/gns/gnocksy/gnocksy.c | |||
@@ -15,64 +15,11 @@ | |||
15 | #include <netdb.h> | 15 | #include <netdb.h> |
16 | #include <arpa/inet.h> | 16 | #include <arpa/inet.h> |
17 | 17 | ||
18 | #define MAXEVENTS 64 | 18 | #include "protocol.h" |
19 | |||
20 | /* The socks phases */ | ||
21 | enum | ||
22 | { | ||
23 | SOCKS5_INIT, | ||
24 | SOCKS5_REQUEST, | ||
25 | SOCKS5_DATA_TRANSFER | ||
26 | }; | ||
27 | |||
28 | /* Client hello */ | ||
29 | struct socks5_client_hello | ||
30 | { | ||
31 | uint8_t version; | ||
32 | uint8_t num_auth_methods; | ||
33 | char* auth_methods; | ||
34 | }; | ||
35 | |||
36 | /* Client socks request */ | ||
37 | struct socks5_client_request | ||
38 | { | ||
39 | uint8_t version; | ||
40 | uint8_t command; | ||
41 | uint8_t resvd; | ||
42 | uint8_t addr_type; | ||
43 | /* | ||
44 | * followed by either an ip4/ipv6 address | ||
45 | * or a domain name with a length field in front | ||
46 | */ | ||
47 | }; | ||
48 | |||
49 | /* Server hello */ | ||
50 | struct socks5_server_hello | ||
51 | { | ||
52 | uint8_t version; | ||
53 | uint8_t auth_method; | ||
54 | }; | ||
55 | |||
56 | /* Struct used to store connection | ||
57 | * information | ||
58 | */ | ||
59 | struct socks5_bridge | ||
60 | { | ||
61 | int fd; | ||
62 | struct socks5_bridge* remote_end; | ||
63 | int status; | ||
64 | }; | ||
65 | 19 | ||
66 | /* Server response to client requests */ | 20 | #define MAXEVENTS 64 |
67 | struct socks5_server_response | ||
68 | { | ||
69 | uint8_t version; | ||
70 | uint8_t reply; | ||
71 | uint8_t reserved; | ||
72 | uint8_t addr_type; | ||
73 | uint8_t addr_port; | ||
74 | }; | ||
75 | 21 | ||
22 | #define DEBUG 1 | ||
76 | 23 | ||
77 | /* | 24 | /* |
78 | * Create an ipv4/6 tcp socket for a given port | 25 | * Create an ipv4/6 tcp socket for a given port |
@@ -154,6 +101,68 @@ setnonblocking (int fd) | |||
154 | return 0; | 101 | return 0; |
155 | } | 102 | } |
156 | 103 | ||
104 | /** | ||
105 | * Checks if name is in tld | ||
106 | * | ||
107 | * @param name the name to check | ||
108 | * @param tld the TLD to check for | ||
109 | * @return -1 if name not in tld | ||
110 | */ | ||
111 | static int | ||
112 | is_tld (const char* name, const char* tld) | ||
113 | { | ||
114 | int offset = 0; | ||
115 | |||
116 | if (strlen (name) <= strlen (tld)) | ||
117 | return -1; | ||
118 | |||
119 | offset = strlen (name) - strlen (tld); | ||
120 | if (strcmp (name+offset, tld) != 0) | ||
121 | return -1; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | |||
127 | /* | ||
128 | * Connect to host specified in phost | ||
129 | * | ||
130 | * @param phost the hostentry containing the IP | ||
131 | * @return fd to the connection or -1 on error | ||
132 | */ | ||
133 | static int | ||
134 | connect_to_domain (struct hostent* phost, uint16_t srv_port) | ||
135 | { | ||
136 | uint32_t srv_ip; | ||
137 | struct sockaddr_in srv_addr; | ||
138 | struct in_addr *sin_addr; | ||
139 | int conn_fd; | ||
140 | |||
141 | |||
142 | sin_addr = (struct in_addr*)(phost->h_addr); | ||
143 | srv_ip = sin_addr->s_addr; | ||
144 | conn_fd = socket(AF_INET, SOCK_STREAM, 0); | ||
145 | memset(&srv_addr, 0, sizeof(srv_addr)); | ||
146 | srv_addr.sin_family = AF_INET; | ||
147 | srv_addr.sin_addr.s_addr = srv_ip; | ||
148 | srv_addr.sin_port = srv_port; | ||
149 | printf("target server: %s:%u\n", inet_ntoa(srv_addr.sin_addr), | ||
150 | ntohs(srv_port)); | ||
151 | |||
152 | if (connect (conn_fd, (struct sockaddr*)&srv_addr, | ||
153 | sizeof (struct sockaddr)) < 0) | ||
154 | { | ||
155 | printf("socket request error...\n"); | ||
156 | close(conn_fd); | ||
157 | return -1; | ||
158 | } | ||
159 | |||
160 | setnonblocking(conn_fd); | ||
161 | |||
162 | return conn_fd; | ||
163 | } | ||
164 | |||
165 | |||
157 | int main ( int argc, char *argv[] ) | 166 | int main ( int argc, char *argv[] ) |
158 | { | 167 | { |
159 | int sfd, s; | 168 | int sfd, s; |
@@ -161,9 +170,28 @@ int main ( int argc, char *argv[] ) | |||
161 | struct epoll_event event; | 170 | struct epoll_event event; |
162 | struct epoll_event *events; | 171 | struct epoll_event *events; |
163 | int ev_states[MAXEVENTS]; | 172 | int ev_states[MAXEVENTS]; |
164 | int j; | 173 | int n, i, j; |
165 | struct socks5_bridge* br; | 174 | struct socks5_bridge* br; |
166 | 175 | ||
176 | struct sockaddr in_addr; | ||
177 | socklen_t in_len; | ||
178 | int infd; | ||
179 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; | ||
180 | |||
181 | int done; | ||
182 | ssize_t count; | ||
183 | char buf[512]; | ||
184 | struct socks5_server_hello hello; | ||
185 | struct socks5_server_response resp; | ||
186 | struct socks5_client_request *req; | ||
187 | struct socks5_bridge* new_br; | ||
188 | char domain[256]; | ||
189 | uint8_t msg[16]; | ||
190 | uint8_t dom_len; | ||
191 | uint16_t req_port; | ||
192 | int conn_fd; | ||
193 | struct hostent *phost; | ||
194 | |||
167 | for (j = 0; j < MAXEVENTS; j++) | 195 | for (j = 0; j < MAXEVENTS; j++) |
168 | ev_states[j] = SOCKS5_INIT; | 196 | ev_states[j] = SOCKS5_INIT; |
169 | 197 | ||
@@ -212,8 +240,6 @@ int main ( int argc, char *argv[] ) | |||
212 | 240 | ||
213 | while (1) | 241 | while (1) |
214 | { | 242 | { |
215 | int n, i; | ||
216 | |||
217 | n = epoll_wait (efd, events, MAXEVENTS, -1); | 243 | n = epoll_wait (efd, events, MAXEVENTS, -1); |
218 | for (i = 0; i < n; i++) | 244 | for (i = 0; i < n; i++) |
219 | { | 245 | { |
@@ -233,11 +259,7 @@ int main ( int argc, char *argv[] ) | |||
233 | /* New connection(s) */ | 259 | /* New connection(s) */ |
234 | while (1) | 260 | while (1) |
235 | { | 261 | { |
236 | struct sockaddr in_addr; | 262 | |
237 | socklen_t in_len; | ||
238 | int infd; | ||
239 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; | ||
240 | |||
241 | in_len = sizeof (in_addr); | 263 | in_len = sizeof (in_addr); |
242 | infd = accept (sfd, &in_addr, &in_len); | 264 | infd = accept (sfd, &in_addr, &in_len); |
243 | if (infd == -1) | 265 | if (infd == -1) |
@@ -284,25 +306,10 @@ int main ( int argc, char *argv[] ) | |||
284 | else | 306 | else |
285 | { | 307 | { |
286 | /* Incoming data */ | 308 | /* Incoming data */ |
287 | int done = 0; | 309 | done = 0; |
288 | 310 | ||
289 | while (1) | 311 | while (1) |
290 | { | 312 | { |
291 | ssize_t count; | ||
292 | char buf[512]; | ||
293 | struct socks5_server_hello hello; | ||
294 | struct socks5_server_response* resp; | ||
295 | struct socks5_client_request* req; | ||
296 | struct socks5_bridge* new_br; | ||
297 | char domain[256]; | ||
298 | uint8_t msg[16]; | ||
299 | uint8_t dom_len; | ||
300 | uint32_t srv_ip; | ||
301 | uint16_t srv_port; | ||
302 | struct sockaddr_in srv_addr; | ||
303 | int conn_fd; | ||
304 | struct hostent *phost; | ||
305 | struct in_addr *sin_addr; | ||
306 | 313 | ||
307 | count = read (br->fd, buf, sizeof (buf)); | 314 | count = read (br->fd, buf, sizeof (buf)); |
308 | 315 | ||
@@ -323,8 +330,15 @@ int main ( int argc, char *argv[] ) | |||
323 | 330 | ||
324 | if (br->status == SOCKS5_DATA_TRANSFER) | 331 | if (br->status == SOCKS5_DATA_TRANSFER) |
325 | { | 332 | { |
333 | if (DEBUG) | ||
334 | { | ||
335 | printf ("Trying to fwd %d bytes from %d to %d!\n" , | ||
336 | count, br->fd, br->remote_end->fd ); | ||
337 | } | ||
326 | if (br->remote_end) | 338 | if (br->remote_end) |
327 | s = write (br->remote_end->fd, buf, count); | 339 | s = write (br->remote_end->fd, buf, count); |
340 | if (DEBUG) | ||
341 | printf ("%d bytes written\n", s); | ||
328 | } | 342 | } |
329 | 343 | ||
330 | if (br->status == SOCKS5_INIT) | 344 | if (br->status == SOCKS5_INIT) |
@@ -338,52 +352,46 @@ int main ( int argc, char *argv[] ) | |||
338 | { | 352 | { |
339 | req = (struct socks5_client_request*)buf; | 353 | req = (struct socks5_client_request*)buf; |
340 | 354 | ||
341 | memset(msg, 0, sizeof(msg)); | 355 | memset(&resp, 0, sizeof(resp)); |
342 | resp = (struct socks5_server_response*)msg; | ||
343 | 356 | ||
344 | if (req->addr_type == 3) | 357 | if (req->addr_type == 3) |
345 | { | 358 | { |
346 | dom_len = *((uint8_t*)(&(req->addr_type) + 1)); | 359 | dom_len = *((uint8_t*)(&(req->addr_type) + 1)); |
347 | memset(domain, 0, sizeof(domain)); | 360 | memset(domain, 0, sizeof(domain)); |
348 | strncpy(domain, (char*)(&(req->addr_type) + 2), dom_len); | 361 | strncpy(domain, (char*)(&(req->addr_type) + 2), dom_len); |
362 | req_port = *((uint16_t*)(&(req->addr_type) + 2 + dom_len)); | ||
349 | 363 | ||
350 | phost = (struct hostent*)gethostbyname (domain); | 364 | phost = (struct hostent*)gethostbyname (domain); |
351 | if (phost == NULL) | 365 | if (phost == NULL) |
352 | { | 366 | { |
353 | printf ("Resolve %s error!\n" , domain ); | 367 | printf ("Resolve %s error!\n" , domain ); |
354 | resp->version = 0x05; | 368 | resp.version = 0x05; |
355 | resp->reply = 0x01; | 369 | resp.reply = 0x01; |
356 | write (br->fd, resp, sizeof (struct socks5_server_response)); | 370 | write (br->fd, &resp, sizeof (struct socks5_server_response)); |
357 | break; | 371 | break; |
358 | } | 372 | } |
359 | 373 | ||
360 | sin_addr = (struct in_addr*)(phost->h_addr); | 374 | if ( -1 != is_tld (domain, ".gnunet") ) |
361 | srv_ip = sin_addr->s_addr; | 375 | { |
362 | srv_port = *((uint16_t*)(&(req->addr_type) + 2 + dom_len)); | 376 | printf("noting implemented for GNUnet %s\n", domain); |
363 | conn_fd = socket(AF_INET, SOCK_STREAM, 0); | 377 | } |
364 | memset(&srv_addr, 0, sizeof(srv_addr)); | 378 | |
365 | srv_addr.sin_family = AF_INET; | 379 | conn_fd = connect_to_domain (phost, req_port); |
366 | srv_addr.sin_addr.s_addr = srv_ip; | 380 | |
367 | srv_addr.sin_port = srv_port; | 381 | if (-1 == conn_fd) |
368 | //printf("target server: %s:%u\n", inet_ntoa(srv_addr.sin_addr), | ||
369 | //ntohs(srv_port)); | ||
370 | |||
371 | if (connect (conn_fd, (struct sockaddr*)&srv_addr, | ||
372 | sizeof (struct sockaddr)) < 0) | ||
373 | { | 382 | { |
374 | printf("socket request error...\n"); | 383 | resp.version = 0x05; |
375 | resp->version = 0x05; | 384 | resp.reply = 0x01; |
376 | resp->reply = 0x01; | 385 | write (br->fd, &resp, 10); |
377 | close(conn_fd); | ||
378 | write (br->fd, resp, 10); | ||
379 | } | 386 | } |
380 | else | 387 | else |
381 | { | 388 | { |
382 | setnonblocking(conn_fd); | 389 | if (DEBUG) |
383 | resp->version = 0x05; | 390 | printf("new remote connection %d to %d\n", br->fd, conn_fd); |
384 | resp->reply = 0x00; | 391 | resp.version = 0x05; |
385 | resp->reserved = 0x00; | 392 | resp.reply = 0x00; |
386 | resp->addr_type = 0x01; | 393 | resp.reserved = 0x00; |
394 | resp.addr_type = 0x01; | ||
387 | 395 | ||
388 | new_br = malloc (sizeof (struct socks5_bridge)); | 396 | new_br = malloc (sizeof (struct socks5_bridge)); |
389 | br->remote_end = new_br; | 397 | br->remote_end = new_br; |
@@ -395,7 +403,7 @@ int main ( int argc, char *argv[] ) | |||
395 | event.data.ptr = new_br; | 403 | event.data.ptr = new_br; |
396 | event.events = EPOLLIN | EPOLLET; | 404 | event.events = EPOLLIN | EPOLLET; |
397 | epoll_ctl (efd, EPOLL_CTL_ADD, conn_fd, &event); | 405 | epoll_ctl (efd, EPOLL_CTL_ADD, conn_fd, &event); |
398 | write (br->fd, resp, 10); | 406 | write (br->fd, &resp, 10); |
399 | } | 407 | } |
400 | 408 | ||
401 | } | 409 | } |
diff --git a/src/gns/gnocksy/protocol.h b/src/gns/gnocksy/protocol.h new file mode 100644 index 000000000..ea076ad1a --- /dev/null +++ b/src/gns/gnocksy/protocol.h | |||
@@ -0,0 +1,57 @@ | |||
1 | |||
2 | |||
3 | /* The socks phases */ | ||
4 | enum | ||
5 | { | ||
6 | SOCKS5_INIT, | ||
7 | SOCKS5_REQUEST, | ||
8 | SOCKS5_DATA_TRANSFER | ||
9 | }; | ||
10 | |||
11 | /* Client hello */ | ||
12 | struct socks5_client_hello | ||
13 | { | ||
14 | uint8_t version; | ||
15 | uint8_t num_auth_methods; | ||
16 | char* auth_methods; | ||
17 | }; | ||
18 | |||
19 | /* Client socks request */ | ||
20 | struct socks5_client_request | ||
21 | { | ||
22 | uint8_t version; | ||
23 | uint8_t command; | ||
24 | uint8_t resvd; | ||
25 | uint8_t addr_type; | ||
26 | /* | ||
27 | * followed by either an ip4/ipv6 address | ||
28 | * or a domain name with a length field in front | ||
29 | */ | ||
30 | }; | ||
31 | |||
32 | /* Server hello */ | ||
33 | struct socks5_server_hello | ||
34 | { | ||
35 | uint8_t version; | ||
36 | uint8_t auth_method; | ||
37 | }; | ||
38 | |||
39 | /* Struct used to store connection | ||
40 | * information | ||
41 | */ | ||
42 | struct socks5_bridge | ||
43 | { | ||
44 | int fd; | ||
45 | struct socks5_bridge* remote_end; | ||
46 | int status; | ||
47 | }; | ||
48 | |||
49 | /* Server response to client requests */ | ||
50 | struct socks5_server_response | ||
51 | { | ||
52 | uint8_t version; | ||
53 | uint8_t reply; | ||
54 | uint8_t reserved; | ||
55 | uint8_t addr_type; | ||
56 | uint8_t add_port[18]; | ||
57 | }; | ||