Commit 3386a64a4d817d03da64318fb028c49c699cee85
v1.3
Yves Rutschle committed on 7/10/2013, 9:07:49 PMParent: b49617923fadbe4429cbab8f4276a70ed0f73ab7
Files changed
sslh.c | changed |
sslh.c | ||
---|---|---|
@@ -27,10 +27,19 @@ | ||
27 | 27 | |
28 | 28 | LynxOS: |
29 | 29 | gcc -o tcproxy tcproxy.c -lnetinet |
30 | 30 | |
31 | +Linux: | |
32 | + cc -o sslh sslh.c -lnet | |
33 | + | |
31 | 34 | HISTORY |
32 | 35 | |
36 | +v1.3: 14MAY2008 | |
37 | + Added parsing for local interface to listen on | |
38 | + Changed default SSL connexion to port 442 (443 doesn't make | |
39 | + sense as a default as we're already listening on 443) | |
40 | + Syslog incoming connexions | |
41 | + | |
33 | 42 | v1.2: 12MAY2008 |
34 | 43 | Fixed compilation warning for AMD64 (Thx Daniel Lange) |
35 | 44 | |
36 | 45 | v1.1: 21MAY2007 |
@@ -45,9 +54,9 @@ | ||
45 | 54 | configurable. |
46 | 55 | |
47 | 56 | */ |
48 | 57 | |
49 | - | |
58 | + | |
50 | 59 | |
51 | 60 | |
52 | 61 | |
53 | 62 | |
@@ -60,8 +69,9 @@ | ||
60 | 69 | |
61 | 70 | |
62 | 71 | |
63 | 72 | |
73 | + | |
64 | 74 | |
65 | 75 | |
66 | 76 | if (res == -1) { \ |
67 | 77 | perror(str); \ |
@@ -71,18 +81,24 @@ | ||
71 | 81 | |
72 | 82 | "sslh v" VERSION "\n" \ |
73 | 83 | "usage:\n" \ |
74 | 84 | "\texport PIDFILE=/var/run/sslhc.pid\n" \ |
75 | -"\tsslh [-t <timeout>] -u <username> -p <listenport> -s [sshhost:]port -l [sslhost:]port [-v]\n" | |
85 | +"\tsslh [-t <timeout>] -u <username> -p [listenaddr:]<listenport> \n" \ | |
86 | +"\t\t-s [sshhost:]port -l [sslhost:]port [-v]\n\n" \ | |
87 | +"-v: verbose\n" \ | |
88 | +"-p: address and port to listen on. default: 0.0.0.0:443\n" \ | |
89 | +"-s: SSH address: where to connect an SSH connexion. default: localhost:22\n" \ | |
90 | +"-l: SSL address: where to connect an SSL connexion.\n" \ | |
91 | +"" | |
76 | 92 | |
77 | 93 | int verbose = 0; /* That's really quite global */ |
78 | 94 | |
79 | -/* Starts a listening socket on specified port. | |
95 | +/* Starts a listening socket on specified address. | |
80 | 96 | Returns file descriptor |
81 | 97 | */ |
82 | -int start_listen_socket(int port) | |
98 | +int start_listen_socket(struct sockaddr *addr) | |
83 | 99 | { |
84 | - struct sockaddr_in saddr; | |
100 | + struct sockaddr_in *saddr = (struct sockaddr_in*)addr; | |
85 | 101 | int sockfd, res, reuse; |
86 | 102 | |
87 | 103 | sockfd = socket(AF_INET, SOCK_STREAM, 0); |
88 | 104 | CHECK_RES_DIE(sockfd, "socket"); |
@@ -90,12 +106,9 @@ | ||
90 | 106 | reuse = 1; |
91 | 107 | res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)); |
92 | 108 | CHECK_RES_DIE(res, "setsockopt"); |
93 | 109 | |
94 | - memset(&saddr, 0, sizeof(saddr)); | |
95 | - saddr.sin_port = htons(port); | |
96 | - | |
97 | - res = bind (sockfd, (struct sockaddr*)&saddr, sizeof(saddr)); | |
110 | + res = bind (sockfd, (struct sockaddr*)saddr, sizeof(*saddr)); | |
98 | 111 | CHECK_RES_DIE(res, "bind"); |
99 | 112 | |
100 | 113 | res = listen (sockfd, 5); |
101 | 114 | CHECK_RES_DIE(res, "listen"); |
@@ -177,12 +190,10 @@ | ||
177 | 190 | |
178 | 191 | /* turns a "hostname:port" string into a struct sockaddr; |
179 | 192 | sock: socket address to which to copy the addr |
180 | 193 | fullname: input string -- it gets clobbered |
181 | -serv: default service/port | |
182 | -(defaults don't work yet) | |
183 | 194 | */ |
184 | -void resolve_name(struct sockaddr *sock, char* fullname, int port) { | |
195 | +void resolve_name(struct sockaddr *sock, char* fullname) { | |
185 | 196 | struct addrinfo *addr, hint; |
186 | 197 | char *serv, *host; |
187 | 198 | int res; |
188 | 199 | |
@@ -190,9 +201,9 @@ | ||
190 | 201 | |
191 | 202 | if (!sep) /* No separator: parameter is just a port */ |
192 | 203 | { |
193 | 204 | serv = fullname; |
194 | - fprintf(stderr, "names must be fully specified as hostname:port for the moment\n"); | |
205 | + fprintf(stderr, "names must be fully specified as hostname:port\n"); | |
195 | 206 | exit(1); |
196 | 207 | } |
197 | 208 | else { |
198 | 209 | host = fullname; |
@@ -214,15 +225,31 @@ | ||
214 | 225 | |
215 | 226 | memcpy(sock, addr->ai_addr, sizeof(*sock)); |
216 | 227 | } |
217 | 228 | |
229 | +/* syslogs who connected to where */ | |
230 | +void log_connexion(int socket, char* target) | |
231 | +{ | |
232 | + struct sockaddr peeraddr; | |
233 | + socklen_t size = sizeof(peeraddr); | |
234 | + char buf[64]; | |
235 | + int res; | |
236 | + | |
237 | + res = getpeername(socket, &peeraddr, &size); | |
238 | + CHECK_RES_DIE(res, "getpeername"); | |
239 | + | |
240 | + syslog(LOG_INFO, "connexion from %s forwarded to %s\n", | |
241 | + sprintaddr(buf, sizeof(buf), &peeraddr), target); | |
242 | + | |
243 | +} | |
244 | + | |
218 | 245 | /* |
219 | 246 | * Settings that depend on the command line. That's less global than verbose * :-) |
220 | 247 | * They're set in main(), but also used in start_shoveler(), and it'd be heavy-handed |
221 | 248 | * to pass it all as parameters |
222 | 249 | */ |
223 | 250 | int timeout = 2; |
224 | -int listen_port = 443; | |
251 | +struct sockaddr addr_listen; | |
225 | 252 | struct sockaddr addr_ssl, addr_ssh; |
226 | 253 | |
227 | 254 | |
228 | 255 | /* Child process that finds out what to connect to and proxies |
@@ -233,8 +260,9 @@ | ||
233 | 260 | struct timeval tv; |
234 | 261 | struct sockaddr *saddr; |
235 | 262 | int res; |
236 | 263 | int out_socket; |
264 | + char *target; | |
237 | 265 | |
238 | 266 | FD_ZERO(&fds); |
239 | 267 | FD_SET(in_socket, &fds); |
240 | 268 | memset(&tv, 0, sizeof(tv)); |
@@ -246,17 +274,17 @@ | ||
246 | 274 | /* Pick the target address depending on whether we timed out or not */ |
247 | 275 | if (FD_ISSET(in_socket, &fds)) { |
248 | 276 | /* The client wrote something to the socket: it's an SSL connection */ |
249 | 277 | saddr = &addr_ssl; |
250 | - if (verbose) | |
251 | - fprintf(stderr, "Forwarding to SSL\n"); | |
278 | + target = "SSL"; | |
252 | 279 | } else { |
253 | 280 | /* The client hasn't written anything and we timed out: connect to SSH */ |
254 | 281 | saddr = &addr_ssh; |
255 | - if (verbose) | |
256 | - fprintf(stderr, "Forwarding to SSH\n"); | |
282 | + target = "SSH"; | |
257 | 283 | } |
258 | 284 | |
285 | + log_connexion(in_socket, target); | |
286 | + | |
259 | 287 | /* Connect the target socket */ |
260 | 288 | out_socket = socket(AF_INET, SOCK_STREAM, 0); |
261 | 289 | res = connect(out_socket, saddr, sizeof(addr_ssl)); |
262 | 290 | CHECK_RES_DIE(res, "connect"); |
@@ -341,9 +369,9 @@ | ||
341 | 369 | sprintaddr(buf, sizeof(buf), &addr_ssl), |
342 | 370 | timeout |
343 | 371 | ); |
344 | 372 | fprintf(stderr, "SSH addr: %s\n", sprintaddr(buf, sizeof(buf), &addr_ssh)); |
345 | - fprintf(stderr, "listening on port %d\n", listen_port); | |
373 | + fprintf(stderr, "listening on %s\n", sprintaddr(buf, sizeof(buf), &addr_listen)); | |
346 | 374 | } |
347 | 375 | |
348 | 376 | int main(int argc, char *argv[]) |
349 | 377 | { |
@@ -355,13 +383,15 @@ | ||
355 | 383 | int in_socket, listen_socket; |
356 | 384 | |
357 | 385 | /* Init defaults */ |
358 | 386 | char *user_name = "nobody"; |
359 | - char ssl_str[] = "localhost:443"; | |
387 | + char listen_str[] = "0.0.0.0:443"; | |
388 | + char ssl_str[] = "localhost:442"; | |
360 | 389 | char ssh_str[] = "localhost:22"; |
361 | 390 | |
362 | - resolve_name(&addr_ssl, ssl_str, 443); | |
363 | - resolve_name(&addr_ssh, ssh_str, 22); | |
391 | + resolve_name(&addr_listen, listen_str); | |
392 | + resolve_name(&addr_ssl, ssl_str); | |
393 | + resolve_name(&addr_ssh, ssh_str); | |
364 | 394 | |
365 | 395 | while ((c = getopt(argc, argv, "t:l:s:p:vu:")) != EOF) { |
366 | 396 | switch (c) { |
367 | 397 | |
@@ -369,17 +399,17 @@ | ||
369 | 399 | timeout = atoi(optarg); |
370 | 400 | break; |
371 | 401 | |
372 | 402 | case 'p': |
373 | - listen_port = atoi(optarg); | |
403 | + resolve_name(&addr_listen, optarg); | |
374 | 404 | break; |
375 | 405 | |
376 | 406 | case 'l': |
377 | - resolve_name(&addr_ssl, optarg, 443); | |
407 | + resolve_name(&addr_ssl, optarg); | |
378 | 408 | break; |
379 | 409 | |
380 | 410 | case 's': |
381 | - resolve_name(&addr_ssh, optarg, 22); | |
411 | + resolve_name(&addr_ssh, optarg); | |
382 | 412 | break; |
383 | 413 | |
384 | 414 | case 'v': |
385 | 415 | verbose += 1; |
@@ -399,9 +429,9 @@ | ||
399 | 429 | printsettings(); |
400 | 430 | |
401 | 431 | setup_signals(); |
402 | 432 | |
403 | - listen_socket = start_listen_socket(listen_port); | |
433 | + listen_socket = start_listen_socket(&addr_listen); | |
404 | 434 | |
405 | 435 | if (fork() > 0) exit(0); /* Detach */ |
406 | 436 | |
407 | 437 | write_pid_file(); |
@@ -411,8 +441,11 @@ | ||
411 | 441 | /* New session -- become group leader */ |
412 | 442 | res = setsid(); |
413 | 443 | CHECK_RES_DIE(res, "setsid: already process leader"); |
414 | 444 | |
445 | + /* Open syslog connexion */ | |
446 | + openlog(argv[0], LOG_CONS, LOG_AUTH); | |
447 | + | |
415 | 448 | /* Main server loop: accept connections, find what they are, fork shovelers */ |
416 | 449 | while (1) |
417 | 450 | { |
418 | 451 | in_socket = accept(listen_socket, 0, 0); |
Built with git-ssb-web