From b58f78f7df7a5596a9d64913f03d4224ace18836 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Sat, 23 Feb 2019 23:42:14 +0000 Subject: [PATCH] add proper bind mode the original bind mode was not well thought out: it restricted the user to only the interface the server was listening on. but one might want to let the server listen only on localhost, but use a different outgoing interface than the default route. --- server.c | 24 +++++++++++++++--------- server.h | 20 +++++++++++++++++--- sockssrv.c | 12 ++++++------ 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/server.c b/server.c index 5319510..700fc9d 100644 --- a/server.c +++ b/server.c @@ -14,9 +14,20 @@ int resolve(const char *host, unsigned short port, struct addrinfo** addr) { return getaddrinfo(host, port_buf, &hints, addr); } -int server_bindtoip(const struct server *server, int fd) { - if(server->bindaddr.v4.sin_family != AF_UNSPEC) - return bind(fd, (struct sockaddr*) &server->bindaddr, server->bindaddrsz); +int resolve_sa(const char *host, unsigned short port, union sockaddr_union *res) { + struct addrinfo *ainfo = 0; + int ret; + SOCKADDR_UNION_AF(res) = AF_UNSPEC; + if((ret = resolve(host, port, &ainfo))) return ret; + memcpy(res, ainfo->ai_addr, ainfo->ai_addrlen); + freeaddrinfo(ainfo); + return 0; +} + +int bindtoip(int fd, union sockaddr_union *bindaddr) { + socklen_t sz = SOCKADDR_UNION_LENGTH(bindaddr); + if(sz) + return bind(fd, (struct sockaddr*) bindaddr, sz); return 0; } @@ -29,7 +40,7 @@ int server_setup(struct server *server, const char* listenip, unsigned short por struct addrinfo *ainfo = 0; if(resolve(listenip, port, &ainfo)) return -1; struct addrinfo* p; - int listenfd; + int listenfd = -1; for(p = ainfo; p; p = p->ai_next) { if((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) continue; @@ -49,10 +60,5 @@ int server_setup(struct server *server, const char* listenip, unsigned short por return -3; } server->fd = listenfd; - if(!resolve(listenip, 0, &ainfo)) { - server->bindaddrsz = ainfo->ai_addrlen; - memcpy(&server->bindaddr, ainfo->ai_addr, ainfo->ai_addrlen); - freeaddrinfo(ainfo); - } else server->bindaddr.v4.sin_family = AF_UNSPEC; return 0; } diff --git a/server.h b/server.h index 4b9f590..69a339f 100644 --- a/server.h +++ b/server.h @@ -15,19 +15,33 @@ union sockaddr_union { struct sockaddr_in6 v6; }; +#define SOCKADDR_UNION_AF(PTR) (PTR)->v4.sin_family + +#define SOCKADDR_UNION_LENGTH(PTR) ( \ + ( SOCKADDR_UNION_AF(PTR) == AF_INET ) ? sizeof((PTR)->v4) : ( \ + ( SOCKADDR_UNION_AF(PTR) == AF_INET6 ) ? sizeof((PTR)->v6) : 0 ) ) + +#define SOCKADDR_UNION_ADDRESS(PTR) ( \ + ( SOCKADDR_UNION_AF(PTR) == AF_INET ) ? (void*) &(PTR)->v4.sin_addr : ( \ + ( SOCKADDR_UNION_AF(PTR) == AF_INET6 ) ? (void*) &(PTR)->v6.sin6_addr : (void*) 0 ) ) + +#define SOCKADDR_UNION_PORT(PTR) ( \ + ( SOCKADDR_UNION_AF(PTR) == AF_INET ) ? (PTR)->v4.sin_port : ( \ + ( SOCKADDR_UNION_AF(PTR) == AF_INET6 ) ? (PTR)->v6.sin6_port : 0 ) ) + struct client { union sockaddr_union addr; int fd; }; struct server { - union sockaddr_union bindaddr; int fd; - socklen_t bindaddrsz; }; int resolve(const char *host, unsigned short port, struct addrinfo** addr); -int server_bindtoip(const struct server *server, int fd); +int resolve_sa(const char *host, unsigned short port, union sockaddr_union *res); +int bindtoip(int fd, union sockaddr_union *bindaddr); + int server_waitclient(struct server *server, struct client* client); int server_setup(struct server *server, const char* listenip, unsigned short port); diff --git a/sockssrv.c b/sockssrv.c index bb852fc..e6977c8 100644 --- a/sockssrv.c +++ b/sockssrv.c @@ -54,7 +54,7 @@ static const char* auth_pass; static sblist* auth_ips; static pthread_mutex_t auth_ips_mutex = PTHREAD_MUTEX_INITIALIZER; static const struct server* server; -static int bind_mode; +static union sockaddr_union bind_addr = {.v4.sin_family = AF_UNSPEC}; enum socksstate { SS_1_CONNECTED, @@ -160,7 +160,7 @@ static int connect_socks_target(unsigned char *buf, size_t n, struct client *cli return -EC_GENERAL_FAILURE; } } - if(bind_mode && server_bindtoip(server, fd) == -1) + if(SOCKADDR_UNION_AF(&bind_addr) != AF_UNSPEC && bindtoip(fd, &bind_addr) == -1) goto eval_errno; if(connect(fd, remote->ai_addr, remote->ai_addrlen) == -1) goto eval_errno; @@ -355,10 +355,10 @@ static int usage(void) { dprintf(2, "MicroSocks SOCKS5 Server\n" "------------------------\n" - "usage: microsocks -1 -b -i listenip -p port -u user -P password\n" + "usage: microsocks -1 -i listenip -p port -u user -P password -b bindaddr\n" "all arguments are optional.\n" "by default listenip is 0.0.0.0 and port 1080.\n\n" - "option -b forces outgoing connections to be bound to the ip specified with -i\n" + "option -b specifies which ip outgoing connections are bound to\n" "option -1 activates auth_once mode: once a specific ip address\n" "authed successfully with user/pass, it is added to a whitelist\n" "and may use the proxy without auth.\n" @@ -379,13 +379,13 @@ int main(int argc, char** argv) { int c; const char *listenip = "0.0.0.0"; unsigned port = 1080; - while((c = getopt(argc, argv, ":1bi:p:u:P:")) != -1) { + while((c = getopt(argc, argv, ":1b:i:p:u:P:")) != -1) { switch(c) { case '1': auth_ips = sblist_new(sizeof(union sockaddr_union), 8); break; case 'b': - bind_mode = 1; + resolve_sa(optarg, 0, &bind_addr); break; case 'u': auth_user = strdup(optarg); -- 2.11.4.GIT