📄 tcpproxy.c
字号:
continue; syslog(LOG_NOTICE, "accept error: %m"); exit (-1); } if ((pid = fork()) < 0) { syslog(LOG_NOTICE, "can't fork process: %m"); exit (-1); } else if (pid == 0) { dup2(connect, 0); dup2(connect, 1); dup2(connect, 2); close (connect); close (bindport[i].sock); return (0); } close (connect); } } } syslog(LOG_NOTICE, "server broke while loop -- terminating"); exit (-1); return (0);}int proxy_request(config_t *x, int cfd){ int sfd, rc, bytes; unsigned long started, now; char buffer[4096]; struct timeval tov; fd_set connection, available; FILE *fp; fp = NULL; if (*x->writefile != 0) { char filename[200]; snprintf (filename, sizeof(filename) - 2, "%s.%d.log", x->writefile, getpid()); if ((fp = fopen(filename, "a")) == NULL) syslog(LOG_NOTICE, "can't open writefile: %s\n", filename); } time((time_t *) &started); cfd = cfd; sfd = fileno(ip_open(x->u.server.name, x->u.server.port)); if (sfd < 0) { char *error; error = get_error(ip_lib_error); syslog(LOG_NOTICE, "connection error: client= %s, server= %s:%u, error= %s\n", x->client, x->u.server.name, x->u.server.port, error); exit (-1); } syslog(LOG_NOTICE, "connect: client= %s, server= %s:%u, timeout= %d", x->client, x->u.server.name, x->u.server.port, x->timeout); FD_ZERO(&connection); FD_SET(cfd, &connection); FD_SET(sfd, &connection); while (1) { memmove(&available, &connection, sizeof(fd_set)); tov.tv_sec = x->timeout; tov.tv_usec = 0; rc = select(sfd + 1, &available, (fd_set *) NULL, (fd_set *) NULL, &tov); if (rc < 0) { syslog(LOG_NOTICE, "select() error: %m\n"); break; } else if (rc == 0) { syslog(LOG_NOTICE, "connection timed out: client= %s, server= %s:%u", x->client, x->u.server.name, x->u.server.port); break; } if (FD_ISSET(cfd, &available)) { if ((bytes = read(0, buffer, sizeof(buffer))) <= 0) shutdown(sfd, 1); else if (write(sfd, buffer, bytes) != bytes) break; if (fp != NULL) { buffer[bytes] = 0; fprintf (fp, "--- CLIENT [%d]:\n", getpid()); fprintf (fp, "%s\n", buffer); fprintf (fp, "\n"); } x->bytes_send = x->bytes_send + bytes; } if (FD_ISSET(sfd, &available)) { if ((bytes = read(sfd, buffer, sizeof(buffer))) <= 0) break; else if (write(1, buffer, bytes) != bytes) break; if (fp != NULL) { buffer[bytes] = 0; fprintf (fp, "--- SERVER [%d]:\n", getpid()); fprintf (fp, "%s\n", buffer); fprintf (fp, "\n"); } x->bytes_received = x->bytes_received + bytes; } } time((time_t *) &now); syslog(LOG_NOTICE, "disconnect: client= %s, server= %s:%u, received= %ld, send= %ld, duration= %ld", x->client, x->u.server.name, x->u.server.port, x->bytes_received, x->bytes_send, now - started); return (0);}unsigned get_interface_info(int pfd, char *ip, int max){ int size; unsigned int port; struct sockaddr_in saddr; size = sizeof(saddr); if (getsockname(pfd, (struct sockaddr *) &saddr, &size) < 0) { syslog(LOG_NOTICE, "can't get interface info: %m"); exit (-1); } copy_string(ip, (char *) inet_ntoa(saddr.sin_addr), max); port = ntohs(saddr.sin_port); return (port);}int get_client_info(config_t *x, int pfd){ int size; struct sockaddr_in saddr; struct in_addr *addr; struct hostent *hostp = NULL; *x->client = 0; size = sizeof(saddr); if (getpeername(pfd, (struct sockaddr *) &saddr, &size) < 0) { return (-1); } copy_string(x->client_ip, (char *) inet_ntoa(saddr.sin_addr), sizeof(x->client_ip)); addr = &saddr.sin_addr, hostp = gethostbyaddr((char *) addr, sizeof (saddr.sin_addr.s_addr), AF_INET); if (hostp == NULL) { strcpy(x->client, x->client_ip); return (0); } strcpy(x->client, hostp->h_name); strlwr(x->client); return (0);}int open_errorlog(char *filename){ int fno; if (use_errorlog == 0) return (0); if ((fno = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0664)) >= 0) dup2(fno, 2); else fprintf (stderr, "%s: can't open %s, using stderr\n", program, filename); return (0);}void missing_arg(int c, char *string){ fprintf (stderr, "%s: missing arg: -%c, %s\n", program, c, string); exit (-1);}int main(int argc, char *argv[], char *envp[]){ int c, i, k, bound; unsigned int port; char *p, option[80], interface[300]; config_t *x; if ((p = strrchr(argv[0], '/')) == NULL) program = argv[0]; else { copy_string(progname, &p[1], sizeof(progname)); program = progname; } x = allocate(sizeof(config_t)); x->timeout = 60; strcpy(x->varname, "PROXY_"); bindport = allocate(sizeof(port_t) * MAX_PORT); openlog(program, LOG_PID, LOG_MAIL); bound = 0; k = 1; while (k < argc && argv[k][0] == '-' && argv[k][1] != 0) { copy_string(option, argv[k++], sizeof(option)); for (i=1; (c = option[i]) != 0; i++) { if (c == 'd') debug = 1; else if (c == 'a') { if (k >= argc) missing_arg(c, "access control program"); copy_string(x->acp, argv[k++], sizeof(x->acp)); } else if (c == 'b') { char addr[300]; if (k >= argc) missing_arg(c, "bind address and port"); copy_string(addr, argv[k++], sizeof(addr)); if ((p = strchr(addr, ':')) == NULL) x->port = getportnum(addr); else { *p++ = 0; x->port = getportnum(p); copy_string(x->interface, addr, sizeof(x->interface)); } bound = 1; standalone = 1; } else if (c == 'e') { if (use_errorlog != 0) { if (k >= argc) missing_arg(c, "logfile name"); copy_string(errorlog, argv[k++], sizeof(errorlog)); } use_errorlog = 1; } else if (c == 'f' || c == 'c') { if (k >= argc) missing_arg(c, "configuration file"); copy_string(configfile, argv[k++], sizeof(configfile)); } else if (c == 'l') { if (k >= argc) missing_arg(c, "logname"); copy_string(logname, argv[k++], sizeof(logname)); } else if (c == 'p') { if (*pidfile == 0) strcpy(pidfile, PIDFILE); else { if (k >= argc) missing_arg(c, "pidfile"); copy_string(pidfile, argv[k++], sizeof(pidfile)); } } else if (c == 's') standalone = 1; else if (c == 't') { if (k >= argc) missing_arg(c, "timeout"); x->timeout = atoi(argv[k++]); if (x->timeout < 1) x->timeout = 60; } else if (c == 'v') { if (k >= argc) missing_arg(c, "varname prefix"); copy_string(x->varname, argv[k++], sizeof(x->varname)); } else if (c == 'w') { if (k >= argc) missing_arg(c, "write file"); copy_string(x->writefile, argv[k++], sizeof(x->writefile)); } else if (c == 'y') x->cleanenv = 1; else if (c == 'z') { if (listports == 0) listports = 1; else listports = 2; } else { fprintf (stderr, "%s: unknown option: -%c\n", program, c); exit (-1); } } } if (*configfile != 0) read_configuration(configfile, x); else if (bound == 0 && k >= argc) { copy_string(configfile, "/etc/tcpproxy.conf", sizeof(configfile)); standalone = 1; read_configuration(configfile, x); } else if (listports == 1) /* ist ok, ein Serverprogramm wird nicht benoetigt */ ; else if (k >= argc) { fprintf (stderr, "%s: missing server\n", program); exit (1); } else { if (*argv[k] == '/' || *argv[k] == '.') { x->proxytype = PROXY_PROGRAM; i = 0; while (k < argc) x->u.program.argv[i++] = argv[k++]; x->u.program.argv[i] = NULL; } else { x->proxytype = PROXY_SERVER; copy_string(x->u.server.name, argv[k++], sizeof(x->u.server.name)); x->u.server.port = get_port(x->u.server.name, 0); if (k < argc) { fprintf (stderr, "%s: extra arguments after server\n", program); exit (1); } } } if (*logname != 0) { copy_string(progname, logname, sizeof(progname)); closelog(); openlog(logname, LOG_PID, LOG_MAIL); } if (first == NULL) { x = new_configuration(x); bindport[binds].port = x->port; bindport[binds].count = 1; binds++; } if (listports == 1) { for (i=0; i<binds; i++) { if (bindport[i].port != 0) printf ("%u\n", bindport[i].port); } exit (0); } else if (listports == 2) { config_t *y; y = first; while (y != NULL) { printf ("%s %u", y->interface, y->port); if (y->proxytype == PROXY_PROGRAM) { int i; printf (" exec:"); for (i=0; y->u.program.argv[i] != NULL; i++) printf (" %s", y->u.program.argv[i]); } else { printf (" proxy:"); printf (" %s %u", y->u.server.name, y->u.server.port); } printf ("\n"); y = y->next; } exit (0); } if (standalone != 0) { int i; char *ip; for (i=0; i<binds; i++) { if (bindport[i].port == 0) continue; /* Mogelt sich irgendwie in die Port-Liste -- 20AUG99wzk */ ip = bindport[i].ip; if (strcmp(ip, "*") == 0 || bindport[i].count > 1) ip = "0.0.0.0"; bindport[i].sock = bind_to_port(strcmp(ip, "0.0.0.0") == 0? "": ip, bindport[i].port); syslog(LOG_NOTICE, "bound to %s:%u", ip, bindport[i].port); } signal(SIGCHLD, SIG_IGN); standalone = 1; } /* * Prozess in den Hintergrund legen. */ if (debug == 0) { if (standalone != 0) { int pid; if ((pid = fork()) < 0) { fprintf (stderr, "%s: can't fork into background\n", program); exit (-1); } else if (pid > 0) exit (0); syslog(LOG_NOTICE, "ready"); } open_errorlog(errorlog); } /* * pidfile schreiben */ if (*pidfile != 0) { FILE *fp; if ((fp = fopen(pidfile, "w")) == NULL) { fprintf (stderr, "%s: can't write pidfile: %s\n", program, pidfile); exit (1); } fprintf (fp, "%d\n", getpid()); fclose (fp); } /* * user id aendern */ if (getuid() != 0 && geteuid() != 0) /* nichts */ ; else if (setgid(gid) != 0 || setuid(uid) != 0) { fprintf (stderr, "%s: can't change uid/gid to %d/%d\n", program, uid, gid); exit (1); } /* * Server ist einsatzbereit */ if (standalone != 0) multiaccept_loop(first); signal(SIGCHLD, SIG_DFL); /* * An dieser Stelle liegt auf stdin/stdout eine TCP/IP-Verbindung * vor. Im standalone-Modus bleibt der Master-Server immer in der * multiaccept-loop. * * Wir fragen zunaechst die Interface-Daten ab. */ port = get_interface_info(0, interface, sizeof(interface)); syslog(LOG_NOTICE, "connected via %s:%u", interface, port); /* * Konfiguration zum Interface suchen, ggf. die Verbindung * terminieren. */ x = find_configuration(interface, port); if (x == NULL && (x = find_configuration(interface, 0)) == NULL) { syslog(LOG_NOTICE, "no configuration found for interface %s:%u", interface, port); exit (-1); } /* * Ok, es existiert eine Konfiguration. Wir uebernehmen die * Interface-Daten. */ copy_string(x->incoming.ip, interface, sizeof(x->incoming.ip)); x->incoming.port = port; get_client_info(x, 0); if (*x->client == 0) { syslog(LOG_NOTICE, "can't get client info"); exit (-1); } /* * access control Programm ausfuehren */ if (*x->acp != 0) { int rc; rc = run_acp(x); if (rc != 0) exit (0); } /* * Server oder Proxy starten */ if (x->proxytype == PROXY_PROGRAM) { syslog(LOG_NOTICE, "starting %s, client= %s", x->u.program.argv[0], x->client); if (x->cleanenv != 0) cleanenv(x, envp); set_variables(x); execvp(x->u.program.argv[0], x->u.program.argv); syslog(LOG_NOTICE, "can't execute %s: %m", x->u.program.argv[0]); exit (1); } else { /* * proxytype ist entweder PROXY_SERVER oder PROXY_DEFAULT. */ if (x->u.server.port == 0) x->u.server.port = x->incoming.port; if (x->u.server.port == 0) { syslog(LOG_NOTICE, "no destination port for interface %s:%u", interface, port); exit (-1); } proxy_request(x, 0); close(0); } exit (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -