diff --git a/README.md b/README.md index 4de3ea934..ed9718f4e 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,12 @@ main: # Listen ipv6 only listen-ipv6-only: false # Bind source address (ipv4|ipv6) - bind-address: '::' + # It is overridden by bind-address-v{4,6} if specified + bind-address: '' + # Bind source address (ipv4) + bind-address-v4: '' + # Bind source address (ipv6) + bind-address-v6: '' # Bind source network interface bind-interface: '' # Domain address type (ipv4|ipv6|unspec) diff --git a/conf/main.yml b/conf/main.yml index 2cf30eb6a..f43ee91a4 100644 --- a/conf/main.yml +++ b/conf/main.yml @@ -14,7 +14,12 @@ main: # Listen ipv6 only listen-ipv6-only: false # Bind source address (ipv4|ipv6) - bind-address: '::' + # It is overridden by bind-address-v{4,6} if specified + bind-address: '' + # Bind source address (ipv4) + bind-address-v4: '' + # Bind source address (ipv6) + bind-address-v6: '' # Bind source network interface bind-interface: '' # Domain address type (ipv4|ipv6|unspec) diff --git a/src/hev-config.c b/src/hev-config.c index b0743e774..5e4e336b7 100644 --- a/src/hev-config.c +++ b/src/hev-config.c @@ -23,7 +23,7 @@ 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_address[2][256]; static char bind_interface[256]; static char auth_file[1024]; static char username[256]; @@ -47,6 +47,8 @@ hev_config_parse_main (yaml_document_t *doc, yaml_node_t *base) const char *udp_addr = NULL; const char *udp_port = NULL; const char *bind_saddr = NULL; + const char *bind_saddr4 = NULL; + const char *bind_saddr6 = NULL; const char *bind_iface = NULL; const char *addr_type = NULL; @@ -85,6 +87,10 @@ hev_config_parse_main (yaml_document_t *doc, yaml_node_t *base) listen_ipv6_only = (0 == strcasecmp (value, "true")) ? 1 : 0; else if (0 == strcmp (key, "bind-address")) bind_saddr = value; + else if (0 == strcmp (key, "bind-address-v4")) + bind_saddr4 = value; + else if (0 == strcmp (key, "bind-address-v6")) + bind_saddr6 = value; else if (0 == strcmp (key, "bind-interface")) bind_iface = value; else if (0 == strcmp (key, "domain-address-type")) @@ -114,8 +120,14 @@ hev_config_parse_main (yaml_document_t *doc, yaml_node_t *base) if (udp_addr) strncpy (udp_listen_address, udp_addr, 256 - 1); - if (bind_saddr) - strncpy (bind_address, bind_saddr, 256 - 1); + if (bind_saddr4 && bind_saddr4[0] != '\0') + strncpy (bind_address[0], bind_saddr4, 256 - 1); + else if (bind_saddr && bind_saddr[0] != '\0') + strncpy (bind_address[0], bind_saddr, 256 - 1); + if (bind_saddr6 && bind_saddr6[0] != '\0') + strncpy (bind_address[1], bind_saddr6, 256 - 1); + else if (bind_saddr && bind_saddr[0] != '\0') + strncpy (bind_address[1], bind_saddr, 256 - 1); if (bind_iface) strncpy (bind_interface, bind_iface, 256 - 1); @@ -383,12 +395,14 @@ hev_config_get_listen_ipv6_only (void) } const char * -hev_config_get_bind_address (void) +hev_config_get_bind_address (int family) { - if ('\0' == bind_address[0]) + int idx = family == AF_INET6; + + if ('\0' == bind_address[idx][0]) return NULL; - return bind_address; + return bind_address[idx]; } const char * diff --git a/src/hev-config.h b/src/hev-config.h index 0b340b5ee..7e21696da 100644 --- a/src/hev-config.h +++ b/src/hev-config.h @@ -23,7 +23,7 @@ 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); +const char *hev_config_get_bind_address (int family); const char *hev_config_get_bind_interface (void); int hev_config_get_domain_address_type (void); diff --git a/src/hev-socks5-session.c b/src/hev-socks5-session.c index 92ec75375..3d0c0253d 100644 --- a/src/hev-socks5-session.c +++ b/src/hev-socks5-session.c @@ -55,11 +55,17 @@ hev_socks5_session_bind (HevSocks5 *self, int fd, const struct sockaddr *dest) HevSocks5Server *srv = HEV_SOCKS5_SERVER (self); const char *saddr; const char *iface; + int family; int res; LOG_D ("%p socks5 session bind", self); - saddr = hev_config_get_bind_address (); + if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)dest)->sin6_addr)) + family = AF_INET; + else + family = AF_INET6; + + saddr = hev_config_get_bind_address (family); iface = hev_config_get_bind_interface (); if (saddr) {