diff --git a/README.md b/README.md index fcb679ea3..339fa88aa 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,10 @@ main: port: 1080 # Listen address (ipv4|ipv6) listen-address: '::' + # UDP listen port + udp-port: 1080 + # UDP listen address (ipv4|ipv6) +# udp-listen-address: '::1' # Listen ipv6 only listen-ipv6-only: false # Bind source address (ipv4|ipv6) diff --git a/conf/main.yml b/conf/main.yml index 286334d46..2cf30eb6a 100644 --- a/conf/main.yml +++ b/conf/main.yml @@ -7,6 +7,10 @@ main: port: 1080 # Listen address (ipv4|ipv6) listen-address: '::' + # UDP listen port + udp-port: 1080 + # UDP listen address (ipv4|ipv6) +# udp-listen-address: '::1' # Listen ipv6 only listen-ipv6-only: false # Bind source address (ipv4|ipv6) diff --git a/src/core b/src/core index c7b485dbc..103d99705 160000 --- a/src/core +++ b/src/core @@ -1 +1 @@ -Subproject commit c7b485dbc32f7b677342a073ecf3edfa887f4dd7 +Subproject commit 103d99705afcc7663a7e7dcee11a94850da263e0 diff --git a/src/hev-config.c b/src/hev-config.c index 335dc89d0..ca149fb6c 100644 --- a/src/hev-config.c +++ b/src/hev-config.c @@ -21,6 +21,8 @@ static unsigned int workers; static int listen_ipv6_only; static char listen_address[256]; static char listen_port[8]; +static char udp_listen_address[256]; +static char udp_listen_port[8]; static char bind_address[256]; static char bind_interface[256]; static char auth_file[1024]; @@ -42,6 +44,8 @@ hev_config_parse_main (yaml_document_t *doc, yaml_node_t *base) yaml_node_pair_t *pair; const char *addr = NULL; const char *port = NULL; + const char *udp_addr = NULL; + const char *udp_port = NULL; const char *bind_saddr = NULL; const char *bind_iface = NULL; const char *addr_type = NULL; @@ -73,6 +77,10 @@ hev_config_parse_main (yaml_document_t *doc, yaml_node_t *base) port = value; else if (0 == strcmp (key, "listen-address")) addr = value; + else if (0 == strcmp (key, "udp-port")) + udp_port = value; + else if (0 == strcmp (key, "udp-listen-address")) + udp_addr = value; else if (0 == strcmp (key, "listen-ipv6-only")) listen_ipv6_only = (0 == strcasecmp (value, "true")) ? 1 : 0; else if (0 == strcmp (key, "bind-address")) @@ -101,6 +109,11 @@ hev_config_parse_main (yaml_document_t *doc, yaml_node_t *base) strncpy (listen_port, port, 8 - 1); strncpy (listen_address, addr, 256 - 1); + if (udp_port) + strncpy (udp_listen_port, udp_port, 8 - 1); + if (udp_addr) + strncpy (udp_listen_address, udp_addr, 256 - 1); + if (bind_saddr) strncpy (bind_address, bind_saddr, 256 - 1); @@ -319,6 +332,24 @@ hev_config_get_listen_port (void) return listen_port; } +const char * +hev_config_get_udp_listen_address (void) +{ + if ('\0' == udp_listen_address[0]) + return NULL; + + return udp_listen_address; +} + +const char * +hev_config_get_udp_listen_port (void) +{ + if ('\0' == udp_listen_port[0]) + return NULL; + + return udp_listen_port; +} + int hev_config_get_listen_ipv6_only (void) { diff --git a/src/hev-config.h b/src/hev-config.h index e760a8668..58d2fab59 100644 --- a/src/hev-config.h +++ b/src/hev-config.h @@ -17,6 +17,8 @@ unsigned int hev_config_get_workers (void); const char *hev_config_get_listen_address (void); const char *hev_config_get_listen_port (void); +const char *hev_config_get_udp_listen_address (void); +const char *hev_config_get_udp_listen_port (void); int hev_config_get_listen_ipv6_only (void); const char *hev_config_get_bind_address (void); diff --git a/src/hev-socks5-session.c b/src/hev-socks5-session.c index 389434b13..33e124b48 100644 --- a/src/hev-socks5-session.c +++ b/src/hev-socks5-session.c @@ -7,6 +7,7 @@ ============================================================================ */ +#include #include #include @@ -92,6 +93,43 @@ hev_socks5_session_bind (HevSocks5 *self, int fd, const struct sockaddr *dest) return 0; } +static int +hev_socks5_session_udp_bind (HevSocks5Server *self, int sock) +{ + struct sockaddr_in6 addr; + const char *saddr; + const char *sport; + socklen_t alen; + int res; + + LOG_D ("%p socks5 session udp bind", self); + + alen = sizeof (struct sockaddr_in6); + saddr = hev_config_get_udp_listen_address (); + sport = hev_config_get_udp_listen_port (); + + if (saddr) { + res = hev_netaddr_resolve (&addr, saddr, NULL); + if (res < 0) + return -1; + } else { + int fd; + + fd = HEV_SOCKS5 (self)->fd; + res = getsockname (fd, (struct sockaddr *)&addr, &alen); + if (res < 0) + return -1; + } + + addr.sin6_port = sport ? htons (strtoul (sport, NULL, 10)) : 0; + + res = bind (sock, (struct sockaddr *)&addr, alen); + if (res < 0) + return -1; + + return 0; +} + int hev_socks5_session_construct (HevSocks5Session *self, int fd) { @@ -137,6 +175,7 @@ hev_socks5_session_class (void) HevObjectClass *okptr = HEV_OBJECT_CLASS (kptr); if (!okptr->name) { + HevSocks5ServerClass *sskptr; HevSocks5Class *skptr; memcpy (kptr, HEV_SOCKS5_SERVER_TYPE, sizeof (HevSocks5ServerClass)); @@ -146,6 +185,9 @@ hev_socks5_session_class (void) skptr = HEV_SOCKS5_CLASS (kptr); skptr->binder = hev_socks5_session_bind; + + sskptr = HEV_SOCKS5_SERVER_CLASS (kptr); + sskptr->binder = hev_socks5_session_udp_bind; } return okptr;