Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configlexer.lex
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ xdp-program-path{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XDP_PROGRAM_PA
xdp-program-load{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XDP_PROGRAM_LOAD; }
xdp-bpffs-path{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XDP_BPFFS_PATH; }
xdp-force-copy{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XDP_FORCE_COPY; }
udp-padding-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_UDP_PADDING_PORT;}
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}

servers={UNQUOTEDLETTER}* {
Expand Down
11 changes: 10 additions & 1 deletion configparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ struct component {
%token VAR_METRICS_INTERFACE
%token VAR_METRICS_PORT
%token VAR_METRICS_PATH
%token VAR_UDP_PADDING_PORT

/* dnstap */
%token VAR_DNSTAP
Expand Down Expand Up @@ -539,7 +540,7 @@ server_option:
{ cfg_parser->opt->tls_cert_bundle = region_strdup(cfg_parser->opt->region, $2); }
| VAR_PROXY_PROTOCOL_PORT number
{
struct proxy_protocol_port_list* elem = region_alloc_zero(
struct port_list* elem = region_alloc_zero(
cfg_parser->opt->region, sizeof(*elem));
elem->port = $2;
elem->next = cfg_parser->opt->proxy_protocol_port;
Expand Down Expand Up @@ -681,6 +682,14 @@ server_option:
cfg_parser->opt->metrics_path = region_strdup(cfg_parser->opt->region, $2);
#endif /* USE_METRICS */
}
| VAR_UDP_PADDING_PORT number
{
struct port_list* elem = region_alloc_zero(
cfg_parser->opt->region, sizeof(*elem));
elem->port = $2;
elem->next = cfg_parser->opt->udp_padding_port;
cfg_parser->opt->udp_padding_port = elem;
}
;

socket_options:
Expand Down
3 changes: 2 additions & 1 deletion edns.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "edns.h"
#include "nsd.h"
#include "query.h"
#include "options.h"

#if !defined(HAVE_SSL) || !defined(HAVE_CRYPTO_MEMCMP)
/* we need fixed time compare, pull it in from tsig.c */
Expand Down Expand Up @@ -119,7 +120,7 @@ edns_handle_option(uint16_t optcode, uint16_t optlen, buffer_type* packet,
}
break;
case PADDING_CODE:
if(query->tls)
if(query->tcp || query->may_pad)
edns->padding = 1;
buffer_skip(packet, optlen);
break;
Expand Down
15 changes: 13 additions & 2 deletions nsd-checkconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,11 +512,17 @@ config_print_zone(nsd_options_type* opt, const char* k, int s, const char *o,
return;
}
if(strcasecmp(o, "proxy_protocol_port") == 0) {
struct proxy_protocol_port_list* p;
struct port_list* p;
for(p = opt->proxy_protocol_port; p; p = p->next)
printf("%d\n", p->port);
return;
}
if(strcasecmp(o, "udp_padding_port") == 0) {
struct port_list* p;
for(p = opt->udp_padding_port; p; p = p->next)
printf("%d\n", p->port);
return;
}
printf("Server option not handled: %s\n", o);
exit(1);
}
Expand Down Expand Up @@ -735,10 +741,15 @@ config_test_print_server(nsd_options_type* opt)
print_string_var("cookie-secret-file:", "");
}
if(opt->proxy_protocol_port) {
struct proxy_protocol_port_list* p;
struct port_list* p;
for(p = opt->proxy_protocol_port; p; p = p->next)
printf("\tproxy-protocol-port: %d\n", p->port);
}
if(opt->udp_padding_port) {
struct port_list* p;
for(p = opt->udp_padding_port; p; p = p->next)
printf("\tudp-padding-port: %d\n", p->port);
}

#ifdef USE_METRICS
printf("\tmetrics-enable: %s\n", opt->metrics_enable?"yes":"no");
Expand Down
5 changes: 5 additions & 0 deletions nsd.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,11 @@ times, additional port numbers can be used for proxy protocol service. The
interface definitions that use this port number expect PROXYv2 proxy protocol
traffic, for UDP, TCP and for TLS service.
.TP
.B udp\-padding\-port:\fR <number>
UDP requests received over this port containing an EDNS0 padding option will,
unlike ordinary UDP requests, be answered with a padded response. The option
may be given more than once.
.TP
.B xdp\-interface:\fR <string>
The interface to use XDP with. This enables the use of AF_XDP sockets for UDP
queries. Default is "", disabled. (EXPERIMENTAL)
Expand Down
6 changes: 2 additions & 4 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ nsd_options_create(region_type* region)
opt->tls_cert_bundle = NULL;
opt->tls_auth_xfr_only = 0;
opt->proxy_protocol_port = NULL;
opt->udp_padding_port = NULL;
opt->answer_cookie = 0;
opt->cookie_secret = NULL;
opt->cookie_staging_secret = NULL;
Expand Down Expand Up @@ -3173,10 +3174,8 @@ resolve_interface_names(struct nsd_options* options)
}

int
sockaddr_uses_proxy_protocol_port(struct nsd_options* options,
struct sockaddr* addr)
sockaddr_uses_port(struct sockaddr* addr, struct port_list* p)
{
struct proxy_protocol_port_list* p;
int port;
#ifdef INET6
struct sockaddr_storage* ss = (struct sockaddr_storage*)addr;
Expand All @@ -3196,7 +3195,6 @@ sockaddr_uses_proxy_protocol_port(struct nsd_options* options,
return 0; /* unknown family */
}
#endif
p = options->proxy_protocol_port;
while(p) {
if(p->port == port)
return 1;
Expand Down
17 changes: 9 additions & 8 deletions options.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct dname;
struct tsig_key;
struct buffer;
struct nsd;
struct proxy_protocol_port_list;
struct port_list;


typedef struct nsd_options nsd_options_type;
Expand Down Expand Up @@ -147,7 +147,9 @@ struct nsd_options {
int tls_auth_xfr_only;

/* proxy protocol port list */
struct proxy_protocol_port_list* proxy_protocol_port;
struct port_list* proxy_protocol_port;
/* udp-padding-port list */
struct port_list* udp_padding_port;

/** remote control section. enable toggle. */
int control_enable;
Expand Down Expand Up @@ -463,9 +465,9 @@ struct tls_auth_options {
char* client_key_pw;
};

/* proxy protocol port option list */
struct proxy_protocol_port_list {
struct proxy_protocol_port_list* next;
/* port option list */
struct port_list {
struct port_list* next;
int port;
};

Expand Down Expand Up @@ -666,8 +668,7 @@ void warn_if_directory(const char* filetype, FILE* f, const char* fname);
* names. */
void resolve_interface_names(struct nsd_options* options);

/* See if the sockaddr port number is listed in the proxy protocol ports. */
int sockaddr_uses_proxy_protocol_port(struct nsd_options* options,
struct sockaddr* addr);
/* See if the sockaddr port number is listed in the ports. */
int sockaddr_uses_port(struct sockaddr* addr, struct port_list* ports);

#endif /* OPTIONS_H */
1 change: 1 addition & 0 deletions query.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ query_reset(query_type *q, size_t maxlen, int is_tcp)
q->remote_addrlen = (socklen_t)sizeof(q->remote_addr);
q->client_addrlen = (socklen_t)sizeof(q->client_addr);
q->is_proxied = 0;
q->may_pad = 0;
q->maxlen = maxlen;
q->reserved_space = 0;
buffer_clear(q->packet);
Expand Down
3 changes: 3 additions & 0 deletions query.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ struct query {

/* if set, the request came through a proxy */
int is_proxied;
/* if set, the response may be padded */
int may_pad;

/* the client address
* the same as remote_addr if not proxied */
#ifdef INET6
Expand Down
17 changes: 11 additions & 6 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ struct udp_handler_data
struct event event;
/* if set, PROXYv2 is expected on this connection */
int pp2_enabled;
/* if set, padding is allowed on this connection */
int may_pad;
};

struct tcp_accept_handler_data {
Expand Down Expand Up @@ -3331,11 +3333,14 @@ add_udp_handler(
data->nsd = nsd;
data->socket = sock;

if(nsd->options->proxy_protocol_port &&
sockaddr_uses_proxy_protocol_port(nsd->options,
(struct sockaddr *)&sock->addr.ai_addr)) {
if(sockaddr_uses_port((struct sockaddr *)&sock->addr.ai_addr,
nsd->options->proxy_protocol_port)) {
data->pp2_enabled = 1;
}
if(sockaddr_uses_port((struct sockaddr *)&sock->addr.ai_addr,
nsd->options->udp_padding_port)) {
data->may_pad = 1;
}

memset(handler, 0, sizeof(*handler));
event_set(handler, sock->s, EV_PERSIST|EV_READ, handle_udp, data);
Expand All @@ -3356,9 +3361,8 @@ add_tcp_handler(
data->nsd = nsd;
data->socket = sock;

if(nsd->options->proxy_protocol_port &&
sockaddr_uses_proxy_protocol_port(nsd->options,
(struct sockaddr *)&sock->addr.ai_addr)) {
if(sockaddr_uses_port((struct sockaddr *)&sock->addr.ai_addr,
nsd->options->proxy_protocol_port)) {
data->pp2_enabled = 1;
}

Expand Down Expand Up @@ -4173,6 +4177,7 @@ handle_udp(int fd, short event, void* arg)
queries[i]->remote_addrlen = msgs[i].msg_hdr.msg_namelen;
queries[i]->client_addrlen = (socklen_t)sizeof(queries[i]->client_addr);
queries[i]->is_proxied = 0;
queries[i]->may_pad = data->may_pad;
q = queries[i];
if (received == -1) {
log_msg(LOG_ERR, "recvmmsg %d failed %s", i, strerror(
Expand Down
16 changes: 0 additions & 16 deletions tpkg/dot_padding.tdir/dot_padding.dsc

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ server:
zonesdir: ""
verbosity: 2
ip-address: 127.0.0.1
ip-address: 127.0.0.1@@UDP_PAD_PORT@
ip-address: 127.0.0.1@@TPKG_DOT_PORT@
udp-padding-port: @UDP_PAD_PORT@
tls-port: @TPKG_DOT_PORT@
xfrdfile: "xfrd.state"
zonelistfile: "zone.list"
tls-service-key: "dot_padding.key"
tls-service-pem: "dot_padding.pem"
tls-service-key: "padding.key"
tls-service-pem: "padding.pem"

zone:
name: "example.com"
zonefile: "dot_padding.zone"
zonefile: "padding.zone"
16 changes: 16 additions & 0 deletions tpkg/padding.tdir/padding.dsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
BaseName: padding
Version: 1.0
Description: Test EDNS0 padding option
CreationDate: za 25 jul 2026 12:48:29 CEST
Maintainer: Willem Toorop
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: padding.pre
Post: padding.post
Test: padding.test
AuxFiles: padding.conf.in padding.zone padding.key padding.pem
Passed:
Failure:
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# #-- dot_padding.post --#
# #-- padding.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
# #-- dot_padding.pre--#
# #-- padding.pre--#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh

# start NSD
get_random_port 2
get_random_port 3
TPKG_PORT=$RND_PORT
TPKG_DOT_PORT=`expr $RND_PORT + 1`
UDP_PAD_PORT=`expr $RND_PORT + 1`
TPKG_DOT_PORT=`expr $RND_PORT + 2`

PRE="../.."
TPKG_NSD_PID="$PRE/nsd.pid.$$"
TPKG_NSD="$PRE/nsd"

# share the vars
echo "export TPKG_PORT=$TPKG_PORT" >> .tpkg.var.test
echo "export UDP_PAD_PORT=$UDP_PAD_PORT" >> .tpkg.var.test
echo "export TPKG_DOT_PORT=$TPKG_DOT_PORT" >> .tpkg.var.test
echo "export TPKG_NSD_PID=$TPKG_NSD_PID" >> .tpkg.var.test

sed -e "s/@TPKG_DOT_PORT@/$TPKG_DOT_PORT/" < dot_padding.conf.in > edit.conf
sed -e "s/@TPKG_DOT_PORT@/$TPKG_DOT_PORT/" \
-e "s/@UDP_PAD_PORT@/$UDP_PAD_PORT/" < padding.conf.in > edit.conf

$TPKG_NSD -c edit.conf -u "" -l nsd.log -p $TPKG_PORT -P $TPKG_NSD_PID
wait_nsd_up nsd.log
Expand Down
Loading
Loading