Skip to content

Commit

Permalink
Merge pull request #72 from X4BNet/feature/ipversion
Browse files Browse the repository at this point in the history
IP Version filtering
  • Loading branch information
nicholaschiasson authored May 29, 2022
2 parents 8b028ae + 1fe7694 commit 4e9e2a4
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
bin/
gitignore/
t/servroot/
.vscode/
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Attributes:
port: Backend's listening port. (Default: 80)
max_ips: IP buffer size. Maximum number of resolved IPs to cache. (Default: 4)
interval: How many seconds to resolve domain name. (Default: 1)
ipver: Only addresses of family IPv4 or IPv6 will be used if defined (Default: 0)
strict: Require the DNS resolution to succeed and return addresses,
otherwise marks the underlying server and peers as down and
forces use of other servers in the upstream block if there
Expand Down
87 changes: 68 additions & 19 deletions src/ngx_http_upstream_jdomain_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@
#define NGX_JDOMAIN_DEFAULT_PORT 80
#define NGX_JDOMAIN_DEFAULT_PORT_LEN 2

#define NGX_JDOMAIN_IPV4 4
#define NGX_JDOMAIN_IPV6 6

#define NGX_JDOMAIN_FAMILY_DEFAULT 0
#define NGX_JDOMAIN_FAMILY_IPV4 AF_INET
#define NGX_JDOMAIN_FAMILY_IPV6 AF_INET6

#define NGX_JDOMAIN_ARG_STR_INTERVAL "interval="
#define NGX_JDOMAIN_ARG_STR_MAX_IPS "max_ips="
#define NGX_JDOMAIN_ARG_STR_PORT "port="
#define NGX_JDOMAIN_ARG_STR_IPVER "ipver="
#define NGX_JDOMAIN_ARG_STR_STRICT "strict"

typedef struct
Expand All @@ -26,6 +34,7 @@ typedef struct
ngx_uint_t max_ips;
in_port_t port;
ngx_uint_t strict;
short addr_family; /* ipver= */
} conf;
struct
{
Expand Down Expand Up @@ -262,6 +271,7 @@ ngx_http_upstream_jdomain_resolve_handler(ngx_resolver_ctx_t *ctx)
{
ngx_http_upstream_jdomain_instance_t *instance;
ngx_uint_t i;
ngx_uint_t f;
ngx_uint_t exists_alt_server;
ngx_uint_t naddrs_prev;
ngx_http_upstream_server_t *server;
Expand Down Expand Up @@ -304,18 +314,27 @@ ngx_http_upstream_jdomain_resolve_handler(ngx_resolver_ctx_t *ctx)
naddrs_prev = instance->state.data.server->naddrs;
instance->state.data.server->naddrs = 0;
/* Copy the resolved sockaddrs and address names (IP:PORT) into our state data buffers, marking associated peers up */
for (i = 0; i < ngx_min(ctx->naddrs, instance->conf.max_ips); i++) {
addr[i].sockaddr = &sockaddr[i].sockaddr;
addr[i].socklen = peerp[i]->socklen = ctx->addrs[i].socklen;
ngx_memcpy(addr[i].sockaddr, ctx->addrs[i].sockaddr, addr[i].socklen);
ngx_inet_set_port(addr[i].sockaddr, instance->conf.port);
addr[i].name.data = &name[i * NGX_SOCKADDR_STRLEN];
addr[i].name.len = peerp[i]->name.len =
ngx_sock_ntop(addr[i].sockaddr, addr[i].socklen, addr[i].name.data, NGX_SOCKADDR_STRLEN, 1);
peerp[i]->down = 0;
f = 0;
for (i = 0; i < ctx->naddrs; i++) {
if (instance->conf.addr_family != NGX_JDOMAIN_FAMILY_DEFAULT &&
instance->conf.addr_family != ctx->addrs[i].sockaddr->sa_family) {
continue;
}
addr[f].sockaddr = &sockaddr[f].sockaddr;
addr[f].socklen = peerp[f]->socklen = ctx->addrs[i].socklen;
ngx_memcpy(addr[f].sockaddr, ctx->addrs[i].sockaddr, addr[f].socklen);
ngx_inet_set_port(addr[f].sockaddr, instance->conf.port);
addr[f].name.data = peerp[f]->name.data = &name[f * NGX_SOCKADDR_STRLEN];
addr[f].name.len = peerp[f]->name.len =
ngx_sock_ntop(addr[f].sockaddr, addr[f].socklen, addr[f].name.data, NGX_SOCKADDR_STRLEN, 1);
peerp[f]->down = 0;
instance->state.data.server->down = 0;
instance->state.data.server->naddrs++;
f++;
if (instance->conf.max_ips == f) {
break;
}
}
instance->state.data.server->naddrs = f;
instance->state.data.naddrs = instance->state.data.server->naddrs;
/* Copy the sockaddr and name of the invalid address (0.0.0.0:0) into the remaining buffers, marking associated peers down */
for (i = instance->state.data.naddrs; i < ngx_min(naddrs_prev, instance->conf.max_ips); i++) {
Expand Down Expand Up @@ -379,6 +398,7 @@ ngx_http_upstream_jdomain_create_instance(ngx_conf_t *cf, ngx_http_upstream_jdom
instance->conf.interval = 1;
instance->conf.max_ips = 4;
instance->conf.port = NGX_JDOMAIN_DEFAULT_PORT;
instance->conf.addr_family = NGX_JDOMAIN_FAMILY_DEFAULT;

instance->state.resolve.status = NGX_JDOMAIN_STATUS_DONE;

Expand Down Expand Up @@ -465,6 +485,7 @@ ngx_http_upstream_jdomain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t num;
ngx_url_t u;
ngx_uint_t i;
ngx_uint_t f;
char *rc;

NGX_JDOMAIN_INVALID_ADDR_SOCKADDR_IN.sin_addr.s_addr = htonl(INADDR_ANY);
Expand Down Expand Up @@ -556,6 +577,26 @@ ngx_http_upstream_jdomain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}

arglen = ngx_strlen(NGX_JDOMAIN_ARG_STR_IPVER);
if (ngx_strncmp(value[i].data, NGX_JDOMAIN_ARG_STR_IPVER, arglen) == 0) {
num = ngx_atoi(value[i].data + arglen, value[i].len - arglen);
switch (num) {
case NGX_JDOMAIN_IPV4:
instance->conf.addr_family = NGX_JDOMAIN_FAMILY_IPV4;
break;
case NGX_JDOMAIN_IPV6:
instance->conf.addr_family = NGX_JDOMAIN_FAMILY_IPV6;
break;
case 0:
// valid as default
break;
default:
goto invalid;
}

continue;
}

arglen = ngx_strlen(NGX_JDOMAIN_ARG_STR_STRICT);
if (value[i].len == arglen && ngx_strncmp(value[i].data, NGX_JDOMAIN_ARG_STR_STRICT, arglen) == 0) {
instance->conf.strict = 1;
Expand Down Expand Up @@ -605,16 +646,24 @@ ngx_http_upstream_jdomain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
name = instance->state.data.names->elts;
sockaddr = instance->state.data.sockaddrs->elts;
/* Copy the resolved sockaddrs and address names (IP:PORT) into our state data buffers */
for (i = 0; i < ngx_min(u.naddrs, instance->conf.max_ips); i++) {
addr[i].name.data = &name[i * NGX_SOCKADDR_STRLEN];
addr[i].name.len = u.addrs[i].name.len;
ngx_memcpy(addr[i].name.data, u.addrs[i].name.data, addr[i].name.len);
addr[i].sockaddr = &sockaddr[i].sockaddr;
addr[i].socklen = u.addrs[i].socklen;
ngx_memcpy(addr[i].sockaddr, u.addrs[i].sockaddr, addr[i].socklen);
server->naddrs++;
f = 0;
for (i = 0; i < u.naddrs; i++) {
if (instance->conf.addr_family != NGX_JDOMAIN_FAMILY_DEFAULT &&
instance->conf.addr_family != u.addrs[i].sockaddr->sa_family) {
continue;
}
addr[f].name.data = &name[f * NGX_SOCKADDR_STRLEN];
addr[f].name.len = u.addrs[i].name.len;
ngx_memcpy(addr[f].name.data, u.addrs[i].name.data, addr[f].name.len);
addr[f].sockaddr = &sockaddr[f].sockaddr;
addr[f].socklen = u.addrs[i].socklen;
ngx_memcpy(addr[f].sockaddr, u.addrs[i].sockaddr, addr[f].socklen);
f++;
if (instance->conf.max_ips == f) {
break;
}
}
instance->state.data.naddrs = server->naddrs;
instance->state.data.naddrs = server->naddrs = f;
/* Copy the sockaddr and address name of the invalid address (0.0.0.0:0) into the remaining buffers */
for (i = instance->state.data.naddrs; i < instance->conf.max_ips; i++) {
addr[i].name.data = &name[i * NGX_SOCKADDR_STRLEN];
Expand Down

0 comments on commit 4e9e2a4

Please sign in to comment.