From 2add32420aa265158182c0ee5669a408dec29835 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Thu, 24 Feb 2005 15:38:09 +0000 Subject: [PATCH] Sync changes from OpenBSD. Most importantly, this adds reverse proxy support. --- libexec/ftp-proxy/ftp-proxy.8 | 23 ++++++++++- libexec/ftp-proxy/ftp-proxy.c | 74 ++++++++++++++++++++++++++++------- libexec/ftp-proxy/getline.c | 8 ++-- libexec/ftp-proxy/util.c | 22 +++++++---- libexec/ftp-proxy/util.h | 21 ++++++---- 5 files changed, 112 insertions(+), 36 deletions(-) diff --git a/libexec/ftp-proxy/ftp-proxy.8 b/libexec/ftp-proxy/ftp-proxy.8 index 8bf2a2e224..994691aa09 100644 --- a/libexec/ftp-proxy/ftp-proxy.8 +++ b/libexec/ftp-proxy/ftp-proxy.8 @@ -1,5 +1,5 @@ -.\" $OpenBSD: ftp-proxy.8,v 1.40 2004/03/16 08:50:07 jmc Exp $ -.\" $DragonFly: src/libexec/ftp-proxy/ftp-proxy.8,v 1.1 2004/09/21 21:25:28 joerg Exp $ +.\" $OpenBSD: ftp-proxy.8,v 1.41 2004/07/06 19:49:11 dhartmei Exp $ +.\" $DragonFly: src/libexec/ftp-proxy/ftp-proxy.8,v 1.2 2005/02/24 15:38:09 joerg Exp $ .\" .\" Copyright (c) 1996-2001 .\" Obtuse Systems Corporation, All rights reserved. @@ -36,14 +36,18 @@ .Nd Internet File Transfer Protocol proxy server .Sh SYNOPSIS .Nm ftp-proxy +.Bk -words .Op Fl AnrVw .Op Fl a Ar address .Op Fl D Ar debuglevel .Op Fl g Ar group .Op Fl M Ar maxport .Op Fl m Ar minport +.Op Fl R Ar address[:port] +.Op Fl S Ar address .Op Fl t Ar timeout .Op Fl u Ar user +.Ek .Sh DESCRIPTION .Nm is a proxy for the Internet File Transfer Protocol. @@ -138,12 +142,27 @@ Without this flag, does not require any IP forwarding or NAT beyond the .Em rdr necessary to capture the FTP control connection. +.It Fl R Ar address:[port] +Reverse proxy mode for FTP servers running behind a NAT gateway. +In this mode, no redirection is needed. +The proxy is run from +.Xr inetd 8 +on the port that external clients connect to (usually 21). +Control connections and passive data connections are forwarded +to the server. .It Fl r Use reverse host .Pq reverse DNS lookups for logging and libwrap use. By default, the proxy does not look up hostnames for libwrap or logging purposes. +.It Fl S Ar address +Source address to use for data connections made by the proxy. +Useful when there are multiple addresses (aliases) available +to the proxy. +Clients may expect data connections to have the same source +address as the control connections, and reject or drop other +connections. .It Fl t Ar timeout Specifies a timeout, in seconds. The proxy will exit and close open connections if it sees no data diff --git a/libexec/ftp-proxy/ftp-proxy.c b/libexec/ftp-proxy/ftp-proxy.c index dff353f896..a69b51cd8d 100644 --- a/libexec/ftp-proxy/ftp-proxy.c +++ b/libexec/ftp-proxy/ftp-proxy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ftp-proxy.c,v 1.35 2004/03/14 21:51:44 dhartmei Exp $ */ -/* $DragonFly: src/libexec/ftp-proxy/ftp-proxy.c,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $OpenBSD: ftp-proxy.c,v 1.38 2004/11/19 00:47:23 jmc Exp $ */ +/* $DragonFly: src/libexec/ftp-proxy/ftp-proxy.c,v 1.2 2005/02/24 15:38:09 joerg Exp $ */ /* * Copyright (c) 1996-2001 @@ -129,6 +129,8 @@ double xfer_start_time; struct sockaddr_in real_server_sa; struct sockaddr_in client_listen_sa; struct sockaddr_in server_listen_sa; +struct sockaddr_in proxy_sa; +struct in_addr src_addr; int client_listen_socket = -1; /* Only used in PASV mode */ int client_data_socket = -1; /* Connected socket to real client */ @@ -139,6 +141,7 @@ int client_data_bytes, server_data_bytes; int AnonFtpOnly; int Verbose; int NatMode; +int ReverseMode; char ClientName[NI_MAXHOST]; char RealServerName[NI_MAXHOST]; @@ -165,17 +168,17 @@ connection_mode_t connection_mode; extern void debuglog(int debug_level, const char *fmt, ...); double wallclock_time(void); void show_xfer_stats(void); -void log_control_command(const char *cmd, int client); +void log_control_command (char *cmd, int client); int new_dataconn(int server); void do_client_cmd(struct csiob *client, struct csiob *server); void do_server_reply(struct csiob *server, struct csiob *client); - static void usage(void) { syslog(LOG_NOTICE, - "usage: %s [-AnrVw] [-a address] [-D debuglevel [-g group]" - " [-M maxport] [-m minport] [-t timeout] [-u user]", __progname); + "usage: %s [-AnrVw] [-a address] [-D debuglevel] [-g group]" + " [-M maxport] [-m minport] [-R address[:port]] [-S address]" + " [-t timeout] [-u user]", __progname); exit(EX_USAGE); } @@ -383,7 +386,7 @@ show_xfer_stats(void) } void -log_control_command (const char *cmd, int client) +log_control_command (char *cmd, int client) { /* log an ftp control command or reply */ const char *logstring; @@ -539,7 +542,7 @@ connect_port_backchannel(void) * getting one bound to port 20 - This is deliberately * not RFC compliant. */ - bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); + bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr)); client_data_socket = get_backchannel_socket(SOCK_STREAM, min_port, max_port, -1, 1, &listen_sa); if (client_data_socket < 0) { @@ -557,7 +560,7 @@ connect_port_backchannel(void) salen = 1; listen_sa.sin_family = AF_INET; - bzero(&listen_sa.sin_addr, sizeof(struct in_addr)); + bcopy(&src_addr, &listen_sa.sin_addr, sizeof(struct in_addr)); listen_sa.sin_port = htons(20); if (setsockopt(client_data_socket, SOL_SOCKET, SO_REUSEADDR, @@ -927,7 +930,10 @@ do_server_reply(struct csiob *server, struct csiob *client) new_dataconn(0); connection_mode = PASV_MODE; - iap = &(server->sa.sin_addr); + if (ReverseMode) + iap = &(proxy_sa.sin_addr); + else + iap = &(server->sa.sin_addr); debuglog(1, "we want client to use %s:%u", inet_ntoa(*iap), htons(client_listen_sa.sin_port)); @@ -975,7 +981,7 @@ main(int argc, char *argv[]) int use_tcpwrapper = 0; #endif /* LIBWRAP */ - while ((ch = getopt(argc, argv, "a:D:g:m:M:t:u:AnVwr")) != -1) { + while ((ch = getopt(argc, argv, "a:D:g:m:M:R:S:t:u:AnVwr")) != -1) { char *p; switch (ch) { case 'a': @@ -1018,6 +1024,41 @@ main(int argc, char *argv[]) case 'r': Use_Rdns = 1; /* look up hostnames */ break; + case 'R': { + char *s, *t; + + if (!*optarg) + usage(); + if ((s = strdup(optarg)) == NULL) { + syslog (LOG_NOTICE, + "Insufficient memory (malloc failed)"); + exit(EX_UNAVAILABLE); + } + memset(&real_server_sa, 0, sizeof(real_server_sa)); + real_server_sa.sin_len = sizeof(struct sockaddr_in); + real_server_sa.sin_family = AF_INET; + t = strchr(s, ':'); + if (t == NULL) + real_server_sa.sin_port = htons(21); + else { + long port = strtol(t + 1, &p, 10); + + if (*p || port <= 0 || port > 65535) + usage(); + real_server_sa.sin_port = htons(port); + *t = 0; + } + real_server_sa.sin_addr.s_addr = inet_addr(s); + if (real_server_sa.sin_addr.s_addr == INADDR_NONE) + usage(); + free(s); + ReverseMode = 1; + break; + } + case 'S': + if (!inet_aton(optarg, &src_addr)) + usage(); + break; case 't': timeout_seconds = strtol(optarg, &p, 10); if (!*optarg || *p) @@ -1053,7 +1094,8 @@ main(int argc, char *argv[]) memset(&client_iob, 0, sizeof(client_iob)); memset(&server_iob, 0, sizeof(server_iob)); - if (get_proxy_env(0, &real_server_sa, &client_iob.sa) == -1) + if (get_proxy_env(0, &real_server_sa, &client_iob.sa, + &proxy_sa) == -1) exit(EX_PROTOCOL); /* @@ -1265,7 +1307,9 @@ main(int argc, char *argv[]) debuglog(3, "transfer: client to server"); rval = xfer_data("client to server", client_data_socket, - server_data_socket); + server_data_socket, + client_iob.sa.sin_addr, + real_server_sa.sin_addr); if (rval <= 0) { close_client_data(); close_server_data(); @@ -1280,7 +1324,9 @@ main(int argc, char *argv[]) debuglog(3, "transfer: server to client"); rval = xfer_data("server to client", server_data_socket, - client_data_socket); + client_data_socket, + real_server_sa.sin_addr, + client_iob.sa.sin_addr); if (rval <= 0) { close_client_data(); close_server_data(); diff --git a/libexec/ftp-proxy/getline.c b/libexec/ftp-proxy/getline.c index 4b72bf2dc1..48b8d81e0a 100644 --- a/libexec/ftp-proxy/getline.c +++ b/libexec/ftp-proxy/getline.c @@ -1,5 +1,5 @@ /* $OpenBSD: getline.c,v 1.15 2003/06/28 01:04:57 deraadt Exp $ */ -/* $DragonFly: src/libexec/ftp-proxy/getline.c,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $DragonFly: src/libexec/ftp-proxy/getline.c,v 1.2 2005/02/24 15:38:09 joerg Exp $ */ /* * Copyright (c) 1985, 1988 Regents of the University of California. @@ -97,7 +97,7 @@ refill_buffer(struct csiob *iobp) /* don't do tiny reads, grow first if we need to */ rqlen = iobp->io_buffer_size - iobp->io_buffer_len; if (rqlen <= 128) { - char *tmp; + unsigned char *tmp; iobp->io_buffer_size += 128; tmp = realloc(iobp->io_buffer, iobp->io_buffer_size); @@ -153,7 +153,7 @@ telnet_getline(struct csiob *iobp, struct csiob *telnet_passthrough) { unsigned char ch; int ix; - char tbuf[100]; + unsigned char tbuf[100]; iobp->line_buffer[0] = '\0'; @@ -237,7 +237,7 @@ telnet_getline(struct csiob *iobp, struct csiob *telnet_passthrough) * nasty. */ if (ix - iobp->next_byte > iobp->line_buffer_size - 5) { - char *tmp; + unsigned char *tmp; iobp->line_buffer_size = 256 + ix - iobp->next_byte; tmp = realloc(iobp->line_buffer, diff --git a/libexec/ftp-proxy/util.c b/libexec/ftp-proxy/util.c index 388467063a..b53cea5faf 100644 --- a/libexec/ftp-proxy/util.c +++ b/libexec/ftp-proxy/util.c @@ -1,5 +1,5 @@ /* $OpenBSD: util.c,v 1.18 2004/01/22 16:10:30 beck Exp $ */ -/* $DragonFly: src/libexec/ftp-proxy/util.c,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $DragonFly: src/libexec/ftp-proxy/util.c,v 1.2 2005/02/24 15:38:09 joerg Exp $ */ /* * Copyright (c) 1996-2001 @@ -32,7 +32,7 @@ * */ -#include +#include #include #include #include @@ -57,6 +57,8 @@ #include "util.h" +extern int ReverseMode; + int Debug_Level; int Use_Rdns; in_addr_t Bind_Addr = INADDR_NONE; @@ -76,14 +78,14 @@ debuglog(int debug_level, const char *fmt, ...) int get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, - struct sockaddr_in *client_sa_ptr) + struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr) { struct pfioc_natlook natlook; socklen_t slen; int fd; - slen = sizeof(*real_server_sa_ptr); - if (getsockname(connected_fd, (struct sockaddr *)real_server_sa_ptr, + slen = sizeof(*proxy_sa_ptr); + if (getsockname(connected_fd, (struct sockaddr *)proxy_sa_ptr, &slen) != 0) { syslog(LOG_ERR, "getsockname() failed (%m)"); return(-1); @@ -95,6 +97,9 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, return(-1); } + if (ReverseMode) + return(0); + /* * Build up the pf natlook structure. * Just for IPv4 right now @@ -102,10 +107,10 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, memset((void *)&natlook, 0, sizeof(natlook)); natlook.af = AF_INET; natlook.saddr.addr32[0] = client_sa_ptr->sin_addr.s_addr; - natlook.daddr.addr32[0] = real_server_sa_ptr->sin_addr.s_addr; + natlook.daddr.addr32[0] = proxy_sa_ptr->sin_addr.s_addr; natlook.proto = IPPROTO_TCP; natlook.sport = client_sa_ptr->sin_port; - natlook.dport = real_server_sa_ptr->sin_port; + natlook.dport = proxy_sa_ptr->sin_port; natlook.direction = PF_OUT; /* @@ -147,7 +152,8 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, * A unit of data is as much as we get with a single read(2) call. */ int -xfer_data(const char *what_read,int from_fd, int to_fd) +xfer_data(const char *what_read,int from_fd, int to_fd, + struct in_addr from __unused, struct in_addr to __unused) { int rlen, offset, xerrno, mark, flags = 0; char tbuf[4096]; diff --git a/libexec/ftp-proxy/util.h b/libexec/ftp-proxy/util.h index 2d872941c7..6cea2f357d 100644 --- a/libexec/ftp-proxy/util.h +++ b/libexec/ftp-proxy/util.h @@ -1,5 +1,5 @@ /* $OpenBSD: util.h,v 1.3 2002/05/23 10:22:14 deraadt Exp $ */ -/* $DragonFly: src/libexec/ftp-proxy/util.h,v 1.1 2004/09/21 21:25:28 joerg Exp $ */ +/* $DragonFly: src/libexec/ftp-proxy/util.h,v 1.2 2005/02/24 15:38:09 joerg Exp $ */ /* * Copyright (c) 1996-2001 @@ -52,13 +52,18 @@ struct csiob { int send_oob_flags; }; -int telnet_getline(struct csiob *iobp, struct csiob *telnet_passthrough); +extern int telnet_getline(struct csiob *iobp, + struct csiob *telnet_passthrough); -int get_proxy_env(int fd, struct sockaddr_in *server_sa_ptr, - struct sockaddr_in *client_sa_ptr); +extern int get_proxy_env(int fd, struct sockaddr_in *server_sa_ptr, + struct sockaddr_in *client_sa_ptr, struct sockaddr_in *proxy_sa_ptr); + +extern int get_backchannel_socket(int type, int min_port, int max_port, + int start_port, int direction, struct sockaddr_in *sap); + +extern int xfer_data(const char *what_read, int from_fd, int to_fd, + struct in_addr from, struct in_addr to); + +extern char *ProgName; -int get_backchannel_socket(int type, int min_port, int max_port, - int start_port, int direction, - struct sockaddr_in *sap); -int xfer_data(const char *what_read, int from_fd, int to_fd); -- 2.41.0