PROXYv2 downstream support (#760)

This commit is contained in:
Yorgos Thessalonikefs 2022-10-03 15:29:47 +02:00 committed by GitHub
parent 7d96a7e3fe
commit c4e51a4cfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 6142 additions and 4791 deletions

View File

@ -130,7 +130,7 @@ util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
util/rtt.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
util/storage/lruhash.c util/storage/slabhash.c util/tcp_conn_limit.c \
util/timehist.c util/tube.c \
util/timehist.c util/tube.c util/proxy_protocol.c \
util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \
validator/autotrust.c validator/val_anchor.c validator/validator.c \
validator/val_kcache.c validator/val_kentry.c validator/val_neg.c \
@ -148,7 +148,7 @@ outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
fptr_wlist.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
slabhash.lo tcp_conn_limit.lo timehist.lo tube.lo winsock_event.lo \
autotrust.lo val_anchor.lo rpz.lo \
autotrust.lo val_anchor.lo rpz.lo proxy_protocol.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
@ -984,6 +984,8 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/neteve
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
$(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/str2wire.h \
$(srcdir)/dnstap/dnstap.h $(srcdir)/services/listen_dnsport.h
proxy_protocol.lo proxy_protocol.o: $(srcdir)/util/proxy_protocol.c config.h \
$(srcdir)/util/proxy_protocol.h $(srcdir)/sldns/sbuffer.h
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@ -1512,7 +1514,7 @@ asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libu
$(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h
streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/net_help.h $(srcdir)/util/proxy_protocol.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h

View File

@ -494,8 +494,8 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
n->c->do_not_close = 0;
comm_point_stop_listening(n->c);
comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT);
memcpy(&n->c->repinfo.addr, &addr, addrlen);
n->c->repinfo.addrlen = addrlen;
memcpy(&n->c->repinfo.remote_addr, &addr, addrlen);
n->c->repinfo.remote_addrlen = addrlen;
if(rc->use_cert) {
n->shake_state = rc_hs_read;
n->ssl = SSL_new(rc->ctx);
@ -3304,7 +3304,7 @@ remote_handshake_later(struct daemon_remote* rc, struct rc_state* s,
if(r == 0)
log_err("remote control connection closed prematurely");
log_addr(VERB_OPS, "failed connection from",
&s->c->repinfo.addr, s->c->repinfo.addrlen);
&s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen);
log_crypto_err("remote control failed ssl");
clean_point(rc, s);
}

View File

@ -521,7 +521,7 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
stats->qhttps++;
}
}
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
stats->qipv6++;
if( (flags&BIT_QR) )
stats->qbit_QR++;

View File

@ -547,7 +547,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
static int
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
struct respip_client_info* cinfo, struct reply_info* rep,
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
struct sockaddr_storage* addr, socklen_t addrlen,
struct ub_packed_rrset_key** alias_rrset,
struct reply_info** encode_repp, struct auth_zones* az)
{
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
@ -574,7 +575,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
if(actinfo.addrinfo) {
respip_inform_print(&actinfo, qinfo->qname,
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
repinfo);
addr, addrlen);
if(worker->stats.extended && actinfo.rpz_used) {
if(actinfo.rpz_disabled)
@ -703,7 +704,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
!partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
repinfo, alias_rrset,
&repinfo->client_addr, repinfo->client_addrlen, alias_rrset,
&encode_rep, worker->env.auth_zones)) {
goto bail_out;
} else if(partial_rep &&
@ -991,12 +992,14 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
* @param w: worker
* @param qinfo: query info. Pointer into packet buffer.
* @param edns: edns info from query.
* @param repinfo: reply info with source address.
* @param addr: client address.
* @param addrlen: client address length.
* @param pkt: packet buffer.
*/
static void
answer_notify(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* pkt, struct comm_reply* repinfo)
answer_notify(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* pkt,
struct sockaddr_storage* addr, socklen_t addrlen)
{
int refused = 0;
int rcode = LDNS_RCODE_NOERROR;
@ -1005,8 +1008,8 @@ answer_notify(struct worker* w, struct query_info* qinfo,
if(!w->env.auth_zones) return;
has_serial = auth_zone_parse_notify_serial(pkt, &serial);
if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
qinfo->qname_len, qinfo->qclass, &repinfo->addr,
repinfo->addrlen, has_serial, serial, &refused)) {
qinfo->qname_len, qinfo->qclass, addr,
addrlen, has_serial, serial, &refused)) {
rcode = LDNS_RCODE_NOERROR;
} else {
if(refused)
@ -1031,7 +1034,7 @@ answer_notify(struct worker* w, struct query_info* qinfo,
"servfail for NOTIFY %sfor %s from", sr, zname);
else snprintf(buf, sizeof(buf),
"received NOTIFY %sfor %s from", sr, zname);
log_addr(VERB_DETAIL, buf, &repinfo->addr, repinfo->addrlen);
log_addr(VERB_DETAIL, buf, addr, addrlen);
}
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
@ -1051,8 +1054,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
{
if(acl == deny) {
if(verbosity >= VERB_ALGO) {
log_acl_action("dropped", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_acl_action("dropped", &repinfo->client_addr,
repinfo->client_addrlen, acl, acladdr);
log_buf(VERB_ALGO, "dropped", c->buffer);
}
comm_point_drop_reply(repinfo);
@ -1063,8 +1066,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
size_t opt_rr_mark;
if(verbosity >= VERB_ALGO) {
log_acl_action("refused", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_acl_action("refused", &repinfo->client_addr,
repinfo->client_addrlen, acl, acladdr);
log_buf(VERB_ALGO, "refuse", c->buffer);
}
@ -1224,12 +1227,24 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
}
static int
deny_refuse_all(struct comm_point* c, enum acl_access acl,
deny_refuse_all(struct comm_point* c, enum acl_access* acl,
struct worker* worker, struct comm_reply* repinfo,
struct acl_addr* acladdr, int ede)
struct acl_addr** acladdr, int ede, int check_proxy)
{
return deny_refuse(c, acl, acl_deny, acl_refuse, worker, repinfo,
acladdr, ede);
if(check_proxy) {
*acladdr = acl_addr_lookup(worker->daemon->acl,
&repinfo->remote_addr, repinfo->remote_addrlen);
} else {
*acladdr = acl_addr_lookup(worker->daemon->acl,
&repinfo->client_addr, repinfo->client_addrlen);
}
/* If there is no ACL based on client IP use the interface ACL. */
if(!(*acladdr) && c->socket) {
*acladdr = c->socket->acl;
}
*acl = acl_get_control(*acladdr);
return deny_refuse(c, *acl, acl_deny, acl_refuse, worker, repinfo,
*acladdr, ede);
}
static int
@ -1241,7 +1256,7 @@ deny_refuse_non_local(struct comm_point* c, enum acl_access acl,
worker, repinfo, acladdr, ede);
}
int
int
worker_handle_request(struct comm_point* c, void* arg, int error,
struct comm_reply* repinfo)
{
@ -1323,29 +1338,30 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* sending src (client)/dst (local service) addresses over DNSTAP from incoming request handler
*/
if(worker->dtenv.log_client_query_messages) {
log_addr(VERB_ALGO, "request from client", &repinfo->addr, repinfo->addrlen);
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
}
#endif
acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
repinfo->addrlen);
/* If there is no ACL based on client IP use the interface ACL. */
if(!acladdr && c->socket) {
acladdr = c->socket->acl;
/* Check deny/refuse ACLs */
if(repinfo->is_proxied) {
if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr,
worker->env.cfg->ede, 1)) != -1) {
if(ret == 1)
goto send_reply;
return ret;
}
}
acl = acl_get_control(acladdr);
if((ret=deny_refuse_all(c, acl, worker, repinfo, acladdr,
worker->env.cfg->ede)) != -1)
{
if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr,
worker->env.cfg->ede, 0)) != -1) {
if(ret == 1)
goto send_reply;
return ret;
}
if((ret=worker_check_request(c->buffer, worker)) != 0) {
verbose(VERB_ALGO, "worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
if(ret != -1) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), ret);
@ -1357,20 +1373,24 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->stats.num_queries++;
/* check if this query should be dropped based on source ip rate limiting */
if(!infra_ip_ratelimit_inc(worker->env.infra_cache, repinfo,
/* check if this query should be dropped based on source ip rate limiting
* NOTE: we always check the repinfo->client_address. IP ratelimiting is
* implicitly disabled for proxies. */
if(!infra_ip_ratelimit_inc(worker->env.infra_cache,
&repinfo->client_addr, repinfo->client_addrlen,
*worker->env.now,
worker->env.cfg->ip_ratelimit_backoff, c->buffer)) {
/* See if we are passed through with slip factor */
if(worker->env.cfg->ip_ratelimit_factor != 0 &&
ub_random_max(worker->env.rnd,
worker->env.cfg->ip_ratelimit_factor) == 0) {
worker->env.cfg->ip_ratelimit_factor) == 0) {
char addrbuf[128];
addr_to_str(&repinfo->addr, repinfo->addrlen,
addrbuf, sizeof(addrbuf));
verbose(VERB_QUERY, "ip_ratelimit allowed through for ip address %s because of slip in ip_ratelimit_factor",
addrbuf);
addr_to_str(&repinfo->client_addr,
repinfo->client_addrlen, addrbuf,
sizeof(addrbuf));
verbose(VERB_QUERY, "ip_ratelimit allowed through for "
"ip address %s because of slip in "
"ip_ratelimit_factor", addrbuf);
} else {
worker->stats.num_queries_ip_ratelimited++;
comm_point_drop_reply(repinfo);
@ -1381,7 +1401,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* see if query is in the cache */
if(!query_info_parse(&qinfo, c->buffer)) {
verbose(VERB_ALGO, "worker parse request: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
@ -1395,13 +1416,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if(worker->env.cfg->log_queries) {
char ip[128];
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
}
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
verbose(VERB_ALGO, "worker request: refused zone transfer.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
@ -1418,7 +1440,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
qinfo.qtype == LDNS_RR_TYPE_MAILB ||
(qinfo.qtype >= 128 && qinfo.qtype <= 248)) {
verbose(VERB_ALGO, "worker request: formerror for meta-type.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
return 0;
@ -1436,7 +1459,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
memset(&reply_edns, 0, sizeof(reply_edns));
reply_edns.edns_present = 1;
reply_edns.udp_size = EDNS_ADVERTISED_SIZE;
@ -1458,7 +1482,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
@ -1472,7 +1497,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->daemon->cfg->harden_short_bufsize) {
verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
(int)edns.udp_size);
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
edns.udp_size = NORMAL_UDP_SIZE;
}
}
@ -1481,12 +1507,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_QUERY,
"worker request: max UDP reply size modified"
" (%d to max-udp-size)", (int)edns.udp_size);
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
edns.udp_size = worker->daemon->cfg->max_udp_size;
}
if(edns.udp_size < LDNS_HEADER_SIZE) {
verbose(VERB_ALGO, "worker request: edns is too small.");
log_addr(VERB_CLIENT, "from", &repinfo->addr, repinfo->addrlen);
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_TC_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
@ -1510,7 +1538,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
LDNS_PACKET_NOTIFY) {
answer_notify(worker, &qinfo, &edns, c->buffer, repinfo);
answer_notify(worker, &qinfo, &edns, c->buffer,
&repinfo->client_addr, repinfo->client_addrlen);
regional_free_all(worker->scratchpad);
goto send_reply;
}
@ -1586,7 +1615,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
sldns_buffer_read_u16_at(c->buffer, 2), &edns);
regional_free_all(worker->scratchpad);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
&repinfo->client_addr, repinfo->client_addrlen);
goto send_reply;
}
@ -1726,9 +1755,9 @@ lookup_cache:
if(verbosity >= VERB_CLIENT) {
if(c->type == comm_udp)
log_addr(VERB_CLIENT, "udp request from",
&repinfo->addr, repinfo->addrlen);
&repinfo->client_addr, repinfo->client_addrlen);
else log_addr(VERB_CLIENT, "tcp request from",
&repinfo->addr, repinfo->addrlen);
&repinfo->client_addr, repinfo->client_addrlen);
}
/* grab a work request structure for this new request */
@ -1760,8 +1789,8 @@ send_reply_rc:
*/
if(worker->dtenv.log_client_response_messages) {
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen);
dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
}
#endif
if(worker->env.cfg->log_replies)
@ -1773,10 +1802,12 @@ send_reply_rc:
/* log original qname, before the local alias was
* used to resolve that CNAME to something else */
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
log_reply_info(NO_VERBOSE, &qinfo, &repinfo->addr, repinfo->addrlen,
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer);
} else {
log_reply_info(NO_VERBOSE, &qinfo, &repinfo->addr, repinfo->addrlen,
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer);
}
}

View File

@ -902,6 +902,10 @@ server:
# Disable TLS for DNS-over-HTTP downstream service.
# http-notls-downstream: no
# The interfaces that use these listed port numbers will support and
# expect PROXYv2. For UDP and TCP/TLS interfaces.
# proxy-protocol-port: portno for each of the port numbers.
# DNS64 prefix. Must be specified when DNS64 is use.
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
# dns64-prefix: 64:ff9b::0/96

View File

@ -656,6 +656,17 @@ Ignored if the option is not available. Default is yes.
Disable use of TLS for the downstream DNS-over-HTTP connections. Useful for
local back end servers. Default is no.
.TP
.B proxy\-protocol\-port: \fI<portnr>
List port numbers as proxy\-protocol\-port, and when interfaces are defined,
eg. with the @port suffix, as this port number, they support and expect PROXYv2.
In this case the proxy address will only be used for the network communication
and initial ACL (check if the proxy itself is denied/refused by configuration).
The proxied address (if any) will then be used as the true client address and
will be used where applicable for logging, ACL, DNSTAP, RPZ and IP ratelimiting.
PROXYv2 is supported for UDP and TCP/TLS listening interfaces.
There is no support for PROXYv2 on a DoH or DNSCrypt listening interface.
Can list multiple, each on a new statement.
.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.

View File

@ -765,7 +765,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
}
else if(qstate->mesh_info->reply_list) {
subnet_option_from_ss(
&qstate->mesh_info->reply_list->query_reply.addr,
&qstate->mesh_info->reply_list->query_reply.client_addr,
&sq->ecs_client_in, qstate->env->cfg);
}

View File

@ -596,15 +596,17 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
{
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
if((qstate->reply && qstate->reply->addrlen != 0) ||
(iq->fail_reply && iq->fail_reply->addrlen != 0)) {
if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
(iq->fail_reply && iq->fail_reply->remote_addrlen != 0)) {
char from[256], frm[512];
if(qstate->reply && qstate->reply->addrlen != 0)
addr_to_str(&qstate->reply->addr, qstate->reply->addrlen,
from, sizeof(from));
if(qstate->reply && qstate->reply->remote_addrlen != 0)
addr_to_str(&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, from,
sizeof(from));
else
addr_to_str(&iq->fail_reply->addr, iq->fail_reply->addrlen,
from, sizeof(from));
addr_to_str(&iq->fail_reply->remote_addr,
iq->fail_reply->remote_addrlen, from,
sizeof(from));
snprintf(frm, sizeof(frm), "from %s", from);
errinf(qstate, frm);
}
@ -2896,8 +2898,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* use dnssec-lame-bypass if it needs to query there.*/
if(qstate->reply) {
struct delegpt_addr* a = delegpt_find_addr(
iq->dp, &qstate->reply->addr,
qstate->reply->addrlen);
iq->dp, &qstate->reply->remote_addr,
qstate->reply->remote_addrlen);
if(a) a->dnsseclame = 1;
}
/* test the answer is from the zone we expected,
@ -2993,9 +2995,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
if(qstate->reply)
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
sock_list_insert(&qstate->reply_origin,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, qstate->region);
if(iq->minimisation_state != DONOT_MINIMISE_STATE
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
@ -3250,9 +3252,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
if(qstate->reply)
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
sock_list_insert(&qstate->reply_origin,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, qstate->region);
verbose(VERB_ALGO, "cleared outbound list for query restart");
/* go to INIT_REQUEST_STATE for new qname. */
return next_state(iq, INIT_REQUEST_STATE);
@ -3266,9 +3268,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
} else if(qstate->reply) {
/* need addr for lameness cache, but we may have
* gotten this from cache, so test to be sure */
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen,
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen,
iq->dp->name, iq->dp->namelen,
*qstate->env->now, dnsseclame, 0,
iq->qchase.qtype))
log_err("mark host lame: out of memory");
@ -3285,8 +3288,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* gotten this from cache, so test to be sure */
verbose(VERB_DETAIL, "mark as REC_LAME");
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen,
&qstate->reply->remote_addr,
qstate->reply->remote_addrlen,
iq->dp->name, iq->dp->namelen,
*qstate->env->now, 0, 1, iq->qchase.qtype))
log_err("mark host lame: out of memory");
}
@ -4016,8 +4020,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
if(!iq->response)
goto handle_it;
log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
&qstate->reply->addr, qstate->reply->addrlen);
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
&qstate->reply->remote_addr, qstate->reply->remote_addrlen);
if(verbosity >= VERB_ALGO)
log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
iq->response->rep);

View File

@ -609,9 +609,9 @@ struct mesh_reply {
struct comm_reply query_reply;
};
%rename(_addr) comm_reply::addr;
%rename(_addr) comm_reply::client_addr;
struct comm_reply {
struct sockaddr_storage addr;
struct sockaddr_storage client_addr;
};
%extend comm_reply {

View File

@ -172,14 +172,14 @@ int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
}
/* Convert reply->addr to string */
/* Convert reply->client_addr to string */
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
{
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
int af = (int)((struct sockaddr_in*) &(reply->client_addr))->sin_family;
void* sinaddr = &((struct sockaddr_in*) &(reply->client_addr))->sin_addr;
if(af == AF_INET6)
sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
sinaddr = &((struct sockaddr_in6*)&(reply->client_addr))->sin6_addr;
dest[0] = 0;
if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
return;

View File

@ -1290,7 +1290,7 @@ respip_set_is_empty(const struct respip_set* set)
void
respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
struct comm_reply* repinfo)
struct sockaddr_storage* addr, socklen_t addrlen)
{
char srcip[128], respip[128], txt[512];
unsigned port;
@ -1300,10 +1300,10 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
if(local_alias)
qname = local_alias->rrset->rk.dname;
port = (unsigned)((repinfo->addr.ss_family == AF_INET) ?
ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port) :
ntohs(((struct sockaddr_in6*)&repinfo->addr)->sin6_port));
addr_to_str(&repinfo->addr, repinfo->addrlen, srcip, sizeof(srcip));
port = (unsigned)((addr->ss_family == AF_INET) ?
ntohs(((struct sockaddr_in*)addr)->sin_port) :
ntohs(((struct sockaddr_in6*)addr)->sin6_port));
addr_to_str(addr, addrlen, srcip, sizeof(srcip));
addr_to_str(&respip_addr->addr, respip_addr->addrlen,
respip, sizeof(respip));
if(respip_actinfo->rpz_log) {

View File

@ -251,11 +251,13 @@ int respip_set_is_empty(const struct respip_set* set);
* @param local_alias: set to a local alias if the query matches an alias in
* a local zone. In this case its owner name will be considered the actual
* query name.
* @param repinfo: reply info containing the client's source address and port.
* @param addr: the client's source address and port.
* @param addrlen: the client's source address length.
*/
void respip_inform_print(struct respip_action_info* respip_actinfo,
uint8_t* qname, uint16_t qtype, uint16_t qclass,
struct local_rrset* local_alias, struct comm_reply* repinfo);
struct local_rrset* local_alias, struct sockaddr_storage* addr,
socklen_t addrlen);
/**
* Find resp_addr in tree, create and add to tree if it does not exist.

View File

@ -834,14 +834,13 @@ static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
/** find data item in array for ip addresses */
static struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
struct comm_reply* repinfo, int wr)
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
{
struct ip_rate_key key;
hashvalue_type h = hash_addr(&(repinfo->addr),
repinfo->addrlen, 0);
hashvalue_type h = hash_addr(addr, addrlen, 0);
memset(&key, 0, sizeof(key));
key.addr = repinfo->addr;
key.addrlen = repinfo->addrlen;
key.addr = *addr;
key.addrlen = addrlen;
key.entry.hash = h;
return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
}
@ -876,10 +875,9 @@ static void infra_create_ratedata(struct infra_cache* infra,
/** create rate data item for ip address */
static void infra_ip_create_ratedata(struct infra_cache* infra,
struct comm_reply* repinfo, time_t timenow)
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow)
{
hashvalue_type h = hash_addr(&(repinfo->addr),
repinfo->addrlen, 0);
hashvalue_type h = hash_addr(addr, addrlen, 0);
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
if(!k || !d) {
@ -887,8 +885,8 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
free(d);
return; /* alloc failure */
}
k->addr = repinfo->addr;
k->addrlen = repinfo->addrlen;
k->addr = *addr;
k->addrlen = addrlen;
lock_rw_init(&k->entry.lock);
k->entry.hash = h;
k->entry.key = k;
@ -985,8 +983,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
sldns_wire2str_class_buf(qinfo->qclass, cs, sizeof(cs));
ip[0]=0;
if(replylist) {
addr_to_str((struct sockaddr_storage *)&replylist->addr,
replylist->addrlen, ip, sizeof(ip));
addr_to_str((struct sockaddr_storage *)&replylist->remote_addr,
replylist->remote_addrlen, ip, sizeof(ip));
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s from %s", buf, lim, qnm, cs, ts, ip);
} else {
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s", buf, lim, qnm, cs, ts);
@ -1054,8 +1052,8 @@ infra_get_mem(struct infra_cache* infra)
}
int infra_ip_ratelimit_inc(struct infra_cache* infra,
struct comm_reply* repinfo, time_t timenow, int backoff,
struct sldns_buffer* buffer)
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int backoff, struct sldns_buffer* buffer)
{
int max;
struct lruhash_entry* entry;
@ -1065,7 +1063,7 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
return 1;
}
/* find or insert ratedata */
entry = infra_find_ip_ratedata(infra, repinfo, 1);
entry = infra_find_ip_ratedata(infra, addr, addrlen, 1);
if(entry) {
int premax = infra_rate_max(entry->data, timenow, backoff);
int* cur = infra_rate_give_second(entry->data, timenow);
@ -1075,8 +1073,7 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
if(premax <= infra_ip_ratelimit && max > infra_ip_ratelimit) {
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
addr_to_str((struct sockaddr_storage *)&repinfo->addr,
repinfo->addrlen, client_ip, sizeof(client_ip));
addr_to_str(addr, addrlen, client_ip, sizeof(client_ip));
qnm[0]=0;
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
@ -1101,6 +1098,6 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
}
/* create */
infra_ip_create_ratedata(infra, repinfo, timenow);
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
return 1;
}

View File

@ -416,15 +416,16 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
/** Update query ratelimit hash and decide
* whether or not a query should be dropped.
* @param infra: infra cache
* @param repinfo: information about client
* @param addr: client address
* @param addrlen: client address length
* @param timenow: what time it is now.
* @param backoff: if backoff is enabled.
* @param buffer: with query for logging.
* @return 1 if it could be incremented. 0 if the increment overshot the
* ratelimit and the query should be dropped. */
int infra_ip_ratelimit_inc(struct infra_cache* infra,
struct comm_reply* repinfo, time_t timenow, int backoff,
struct sldns_buffer* buffer);
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int backoff, struct sldns_buffer* buffer);
/**
* Get memory used by the infra cache.

View File

@ -1093,11 +1093,13 @@ make_sock_port(int stype, const char* ifname, const char* port,
* @param list: list head. changed.
* @param s: fd.
* @param ftype: if fd is UDP.
* @param pp2_enabled: if PROXYv2 is enabled for this port.
* @param ub_sock: socket with address.
* @return false on failure. list in unchanged then.
*/
static int
port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unbound_socket* ub_sock)
port_insert(struct listen_port** list, int s, enum listen_type ftype,
int pp2_enabled, struct unbound_socket* ub_sock)
{
struct listen_port* item = (struct listen_port*)malloc(
sizeof(struct listen_port));
@ -1106,6 +1108,7 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unb
item->next = *list;
item->fd = s;
item->ftype = ftype;
item->pp2_enabled = pp2_enabled;
item->socket = ub_sock;
*list = item;
return 1;
@ -1201,6 +1204,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param ssl_port: ssl service port number
* @param tls_additional_port: list of additional ssl service port numbers.
* @param https_port: DoH service port number
* @param proxy_protocol_port: list of PROXYv2 port numbers.
* @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
* set to false on exit if reuseport failed due to no kernel support.
* @param transparent: set IP_TRANSPARENT socket option.
@ -1217,25 +1221,30 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int https_port,
struct config_strlist* proxy_protocol_port,
int* reuseport, int transparent, int tcp_mss, int freebind,
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
{
int s, noip6=0;
int is_https = if_is_https(ifname, port, https_port);
int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
int nodelay = is_https && http2_nodelay;
struct unbound_socket* ub_sock;
#ifdef USE_DNSCRYPT
int is_dnscrypt = ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
(!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
#else
int is_dnscrypt = 0;
(void)dnscrypt_port;
#endif
if(!do_udp && !do_tcp)
return 0;
if(is_pp2) {
if(is_dnscrypt) {
fatal_exit("PROXYv2 and DNSCrypt combination not "
"supported!");
} else if(is_https) {
fatal_exit("PROXYv2 and DoH combination not "
"supported!");
}
}
if(do_auto) {
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
@ -1260,7 +1269,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
ub_sock)) {
is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
@ -1283,7 +1292,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
return 0;
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udp_dnscrypt:listen_type_udp, ub_sock)) {
?listen_type_udp_dnscrypt:listen_type_udp,
is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
@ -1318,7 +1328,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(is_ssl)
verbose(VERB_ALGO, "setup TCP for SSL service");
if(!port_insert(list, s, port_type, ub_sock)) {
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
@ -1407,14 +1417,16 @@ listen_create(struct comm_base* base, struct listen_port* ports,
if(ports->ftype == listen_type_udp ||
ports->ftype == listen_type_udp_dnscrypt) {
cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket);
front->udp_buff, ports->pp2_enabled, cb,
cb_arg, ports->socket);
} else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
harden_large_queries, 0, NULL,
tcp_conn_limit, bufsize, front->udp_buff,
ports->ftype, cb, cb_arg, ports->socket);
ports->ftype, ports->pp2_enabled, cb, cb_arg,
ports->socket);
} else if(ports->ftype == listen_type_ssl ||
ports->ftype == listen_type_http) {
cp = comm_point_create_tcp(base, ports->fd,
@ -1422,7 +1434,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
harden_large_queries,
http_max_streams, http_endpoint,
tcp_conn_limit, bufsize, front->udp_buff,
ports->ftype, cb, cb_arg, ports->socket);
ports->ftype, ports->pp2_enabled, cb, cb_arg,
ports->socket);
if(ports->ftype == listen_type_http) {
if(!sslctx && !http_notls) {
log_warn("HTTPS port configured, but "
@ -1448,7 +1461,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
} else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt) {
cp = comm_point_create_udp_ancil(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket);
front->udp_buff, ports->pp2_enabled, cb,
cb_arg, ports->socket);
}
if(!cp) {
log_err("can't create commpoint");
@ -1783,7 +1797,9 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port,
cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1798,7 +1814,9 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port,
cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1816,7 +1834,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1831,7 +1850,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1848,7 +1868,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
@ -1863,7 +1884,8 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->https_port, cfg->proxy_protocol_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {

View File

@ -128,7 +128,10 @@ struct listen_port {
int fd;
/** type of file descriptor, udp or tcp */
enum listen_type ftype;
/** fill in unbpound_socket structure for every opened socket at Unbound startup */
/** if the port should support PROXYv2 */
int pp2_enabled;
/** fill in unbound_socket structure for every opened socket at
* Unbound startup */
struct unbound_socket* socket;
};

View File

@ -1744,13 +1744,13 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
/** print log information for an inform zone query */
static void
lz_inform_print(struct local_zone* z, struct query_info* qinfo,
struct comm_reply* repinfo)
struct sockaddr_storage* addr, socklen_t addrlen)
{
char ip[128], txt[512];
char zname[LDNS_MAX_DOMAINLEN+1];
uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
uint16_t port = ntohs(((struct sockaddr_in*)addr)->sin_port);
dname_str(z->name, zname);
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
addr_to_str(addr, addrlen, ip, sizeof(ip));
snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip,
(unsigned)port);
log_nametypeclass(NO_VERBOSE, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
@ -1765,7 +1765,8 @@ lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
struct local_zone_override* lzo;
if(repinfo && override_tree) {
lzo = (struct local_zone_override*)addr_tree_lookup(
override_tree, &repinfo->addr, repinfo->addrlen);
override_tree, &repinfo->client_addr,
repinfo->client_addrlen);
if(lzo && lzo->type) {
verbose(VERB_ALGO, "local zone override to type %s",
local_zone_type2str(lzo->type));
@ -1888,7 +1889,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
lzt == local_zone_inform_deny ||
lzt == local_zone_inform_redirect)
&& repinfo)
lz_inform_print(z, qinfo, repinfo);
lz_inform_print(z, qinfo, &repinfo->client_addr,
repinfo->client_addrlen);
if(lzt != local_zone_always_refuse
&& lzt != local_zone_always_transparent

View File

@ -806,7 +806,7 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
/* Fake the ECS data from the client's IP */
struct ecs_data ecs;
memset(&ecs, 0, sizeof(ecs));
subnet_option_from_ss(&rep->addr, &ecs, mesh->env->cfg);
subnet_option_from_ss(&rep->client_addr, &ecs, mesh->env->cfg);
if(ecs.subnet_validdata == 0) {
log_err("prefetch_subnet subnet_option_from_ss: invalid data");
return;
@ -1488,8 +1488,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
}
/* Log reply sent */
if(m->s.env->cfg->log_replies) {
log_reply_info(NO_VERBOSE, &m->s.qinfo, &r->query_reply.addr,
r->query_reply.addrlen, duration, 0, r_buffer);
log_reply_info(NO_VERBOSE, &m->s.qinfo,
&r->query_reply.client_addr,
r->query_reply.client_addrlen, duration, 0, r_buffer);
}
}
@ -1530,7 +1531,8 @@ void mesh_query_done(struct mesh_state* mstate)
respip_inform_print(mstate->s.respip_action_info,
r->qname, mstate->s.qinfo.qtype,
mstate->s.qinfo.qclass, r->local_alias,
&r->query_reply);
&r->query_reply.client_addr,
r->query_reply.client_addrlen);
if(mstate->s.env->cfg->stat_extended &&
mstate->s.respip_action_info->rpz_used) {
if(mstate->s.respip_action_info->rpz_disabled)
@ -2180,7 +2182,8 @@ mesh_serve_expired_callback(void* arg)
if(actinfo.addrinfo) {
respip_inform_print(&actinfo, r->qname,
qstate->qinfo.qtype, qstate->qinfo.qclass,
r->local_alias, &r->query_reply);
r->local_alias, &r->query_reply.client_addr,
r->query_reply.client_addrlen);
if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
if(actinfo.rpz_disabled)

View File

@ -721,12 +721,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
pend->next_free = NULL;
pend->query = w;
pend->reuse.outnet = w->outnet;
pend->c->repinfo.addrlen = w->addrlen;
pend->c->repinfo.remote_addrlen = w->addrlen;
pend->c->tcp_more_read_again = &pend->reuse.cp_more_read_again;
pend->c->tcp_more_write_again = &pend->reuse.cp_more_write_again;
pend->reuse.cp_more_read_again = 0;
pend->reuse.cp_more_write_again = 0;
memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen);
memcpy(&pend->c->repinfo.remote_addr, &w->addr, w->addrlen);
pend->reuse.pending = pend;
/* Remove from tree in case the is_ssl will be different and causes the
@ -1417,11 +1417,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
/* setup lookup key */
key.id = (unsigned)LDNS_ID_WIRE(sldns_buffer_begin(c->buffer));
memcpy(&key.addr, &reply_info->addr, reply_info->addrlen);
key.addrlen = reply_info->addrlen;
memcpy(&key.addr, &reply_info->remote_addr, reply_info->remote_addrlen);
key.addrlen = reply_info->remote_addrlen;
verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id);
log_addr(VERB_ALGO, "Incoming reply addr =",
&reply_info->addr, reply_info->addrlen);
&reply_info->remote_addr, reply_info->remote_addrlen);
/* find it, see if this thing is a valid query response */
verbose(VERB_ALGO, "lookup size is %d entries", (int)outnet->pending->count);
@ -1690,7 +1690,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
return NULL;
}
pc->cp = comm_point_create_udp(outnet->base, -1,
outnet->udp_buff, outnet_udp_cb, outnet, NULL);
outnet->udp_buff, 0, outnet_udp_cb, outnet, NULL);
if(!pc->cp) {
log_err("malloc failed");
free(pc);
@ -3103,8 +3103,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
rep = &r2;
r2.c = c;
}
memcpy(&rep->addr, &sq->addr, sq->addrlen);
rep->addrlen = sq->addrlen;
memcpy(&rep->remote_addr, &sq->addr, sq->addrlen);
rep->remote_addrlen = sq->addrlen;
serviced_callbacks(sq, error, c, rep);
return 0;
}
@ -3582,7 +3582,7 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
if(fd == -1) {
return NULL;
}
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff,
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff, 0,
cb, cb_arg, NULL);
if(!cp) {
log_err("malloc failure");
@ -3670,8 +3670,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
close(fd);
return 0;
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
cp->repinfo.remote_addrlen = to_addrlen;
memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
/* setup for SSL (if needed) */
if(ssl) {
@ -3746,8 +3746,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
close(fd);
return 0;
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
cp->repinfo.remote_addrlen = to_addrlen;
memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
/* setup for SSL (if needed) */
if(ssl) {

View File

@ -1392,11 +1392,13 @@ log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
dnamestr[0]=0;
}
if(repinfo) {
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
addr_to_str(&ms->mesh_info->reply_list->query_reply.addr, ms->mesh_info->reply_list->query_reply.addrlen, ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.addr)->sin_port);
addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
ms->mesh_info->reply_list->query_reply.client_addrlen,
ip, sizeof(ip));
port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
} else {
ip[0]=0;
port = 0;
@ -1468,7 +1470,9 @@ rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qin
}
z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
qinfo->qclass, 0, 0, 0);
node = rpz_ipbased_trigger_lookup(r->client_set, &repinfo->addr, repinfo->addrlen, "clientip");
node = rpz_ipbased_trigger_lookup(r->client_set,
&repinfo->client_addr, repinfo->client_addrlen,
"clientip");
if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
if(r->log)
log_rpz_apply((node?"clientip":"qname"),

View File

@ -338,6 +338,8 @@ interfacechecks(struct config_file* cfg)
int i, j, i2, j2;
char*** resif = NULL;
int* num_resif = NULL;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
if(cfg->num_ifs != 0) {
resif = (char***)calloc(cfg->num_ifs, sizeof(char**));
@ -359,9 +361,21 @@ interfacechecks(struct config_file* cfg)
fatal_exit("could not resolve interface names, for %s",
cfg->ifs[i]);
}
/* check for port combinations that are not supported */
if(if_is_pp2(resif[i][0], portbuf, cfg->proxy_protocol_port)) {
if(if_is_dnscrypt(resif[i][0], portbuf,
cfg->dnscrypt_port)) {
fatal_exit("PROXYv2 and DNSCrypt combination not "
"supported!");
} else if(if_is_https(resif[i][0], portbuf,
cfg->https_port)) {
fatal_exit("PROXYv2 and DoH combination not "
"supported!");
}
}
/* search for duplicates in the returned addresses */
for(j=0; j<num_resif[i]; j++) {
if(!extstrtoaddr(resif[i][j], &a, &alen, UNBOUND_DNS_PORT)) {
if(!extstrtoaddr(resif[i][j], &a, &alen, cfg->port)) {
if(strcmp(cfg->ifs[i], resif[i][j]) != 0)
fatal_exit("cannot parse interface address '%s' from the interface specified as '%s'",
resif[i][j], cfg->ifs[i]);

View File

@ -16,7 +16,7 @@ NEED_WHOAMI='07-confroot.tdir'
NEED_IPV6='fwd_ancil.tdir fwd_tcp_tc6.tdir stub_udp6.tdir edns_cache.tdir'
NEED_NOMINGW='tcp_sigpipe.tdir 07-confroot.tdir 08-host-lib.tdir fwd_ancil.tdir'
NEED_DNSCRYPT_PROXY='dnscrypt_queries.tdir dnscrypt_queries_chacha.tdir'
NEED_UNSHARE='acl_interface.tdir'
NEED_UNSHARE='acl_interface.tdir proxy_protocol.tdir'
# test if dig and ldns-testns are available.
test_tool_avail "dig"

View File

@ -384,8 +384,8 @@ answer_callback_from_entry(struct replay_runtime* runtime,
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
pend->tcp_pkt_counter);
repinfo.c = &c;
repinfo.addrlen = pend->addrlen;
memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
repinfo.remote_addrlen = pend->addrlen;
memcpy(&repinfo.remote_addr, &pend->addr, pend->addrlen);
if(!pend->serviced) {
if(entry && entry->reply_list->next &&
pend->tcp_pkt_counter < count_reply_packets(entry)) {
@ -415,7 +415,7 @@ answer_check_it(struct replay_runtime* runtime)
tr = transport_udp;
if((runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
&ans->repinfo.addr, ans->repinfo.addrlen) == 0) &&
&ans->repinfo.remote_addr, ans->repinfo.remote_addrlen) == 0) &&
find_match(runtime->now->match, ans->pkt,
ans->pkt_len, tr)) {
log_info("testbound matched event entry from line %d",
@ -453,10 +453,12 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
if(!repinfo.c)
fatal_exit("out of memory in fake_front_query");
repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
repinfo.remote_addrlen = (socklen_t)sizeof(struct sockaddr_in);
if(todo->addrlen != 0) {
repinfo.addrlen = todo->addrlen;
memcpy(&repinfo.addr, &todo->addr, todo->addrlen);
repinfo.remote_addrlen = todo->addrlen;
memcpy(&repinfo.remote_addr, &todo->addr, todo->addrlen);
repinfo.client_addrlen = todo->addrlen;
memcpy(&repinfo.client_addr, &todo->addr, todo->addrlen);
}
repinfo.c->fd = -1;
repinfo.c->ev = (struct internal_event*)runtime;
@ -510,8 +512,8 @@ fake_pending_callback(struct replay_runtime* runtime,
p->pkt_len, p->tcp_pkt_counter);
}
repinfo.c = &c;
repinfo.addrlen = p->addrlen;
memcpy(&repinfo.addr, &p->addr, p->addrlen);
repinfo.remote_addrlen = p->addrlen;
memcpy(&repinfo.remote_addr, &p->addr, p->addrlen);
if(!p->serviced) {
if(todo->match && todo->match->reply_list->next && !error &&
p->tcp_pkt_counter < count_reply_packets(todo->match)) {
@ -1663,6 +1665,7 @@ int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype),
struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer),
int ATTR_UNUSED(pp2_enabled),
comm_point_callback_type* ATTR_UNUSED(callback),
void* ATTR_UNUSED(callback_arg),
struct unbound_socket* ATTR_UNUSED(socket))

View File

@ -49,6 +49,7 @@
#include "util/locks.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/proxy_protocol.h"
#include "util/data/msgencode.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
@ -71,6 +72,7 @@ static void usage(char* argv[])
printf("usage: %s [options] name type class ...\n", argv[0]);
printf(" sends the name-type-class queries over TCP.\n");
printf("-f server what ipaddr@portnr to send the queries to\n");
printf("-p client what ipaddr@portnr to include in PROXYv2\n");
printf("-u use UDP. No retries are attempted.\n");
printf("-n do not wait for an answer.\n");
printf("-a print answers as they arrive.\n");
@ -82,18 +84,17 @@ static void usage(char* argv[])
/** open TCP socket to svr */
static int
open_svr(const char* svr, int udp)
open_svr(const char* svr, int udp, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
struct sockaddr_storage addr;
socklen_t addrlen;
int fd = -1;
/* svr can be ip@port */
memset(&addr, 0, sizeof(addr));
if(!extstrtoaddr(svr, &addr, &addrlen, UNBOUND_DNS_PORT)) {
memset(addr, 0, sizeof(*addr));
if(!extstrtoaddr(svr, addr, addrlen, UNBOUND_DNS_PORT)) {
printf("fatal: bad server specs '%s'\n", svr);
exit(1);
}
fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET,
fd = socket(addr_is_ip6(addr, *addrlen)?PF_INET6:PF_INET,
udp?SOCK_DGRAM:SOCK_STREAM, 0);
if(fd == -1) {
#ifndef USE_WINSOCK
@ -103,7 +104,7 @@ open_svr(const char* svr, int udp)
#endif
exit(1);
}
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
if(connect(fd, (struct sockaddr*)addr, *addrlen) < 0) {
#ifndef USE_WINSOCK
perror("connect() error");
#else
@ -116,11 +117,12 @@ open_svr(const char* svr, int udp)
/** write a query over the TCP fd */
static void
write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
sldns_buffer* proxy_buf, int pp2_parsed,
const char* strname, const char* strtype, const char* strclass)
{
struct query_info qinfo;
uint16_t len;
size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf);
/* qname */
qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
if(!qinfo.qname) {
@ -152,9 +154,27 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
attach_edns_record(buf, &edns);
}
/* we need to send the PROXYv2 information in every UDP message */
if(udp && pp2_parsed) {
/* append the proxy_buf with the buf's content
* and use that for sending */
if(sldns_buffer_capacity(proxy_buf) <
sldns_buffer_limit(proxy_buf) +
sldns_buffer_limit(buf)) {
printf("buffer too small for packet + proxy");
exit(1);
}
sldns_buffer_clear(proxy_buf);
sldns_buffer_skip(proxy_buf, proxy_buf_limit);
sldns_buffer_write(proxy_buf, sldns_buffer_begin(buf),
sldns_buffer_limit(buf));
sldns_buffer_flip(proxy_buf);
buf = proxy_buf;
}
/* send it */
if(!udp) {
len = (uint16_t)sldns_buffer_limit(buf);
uint16_t len = (uint16_t)sldns_buffer_limit(buf);
len = htons(len);
if(ssl) {
if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
@ -167,7 +187,7 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
#ifndef USE_WINSOCK
perror("send() len failed");
#else
printf("send len: %s\n",
printf("send len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -182,17 +202,20 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
}
} else {
if(send(fd, (void*)sldns_buffer_begin(buf),
sldns_buffer_limit(buf), 0) <
sldns_buffer_limit(buf), 0) <
(ssize_t)sldns_buffer_limit(buf)) {
#ifndef USE_WINSOCK
perror("send() data failed");
#else
printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
printf("send data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
/* reset the proxy_buf for next packet */
sldns_buffer_set_limit(proxy_buf, proxy_buf_limit);
free(qinfo.qname);
}
@ -224,7 +247,7 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
#ifndef USE_WINSOCK
perror("read() len failed");
#else
printf("read len: %s\n",
printf("read len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -243,12 +266,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
if(r != (int)len)
fatal_exit("ssl_read %d of %d", r, len);
} else {
if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
(ssize_t)len) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
printf("read data: %s\n",
printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -257,12 +280,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
} else {
ssize_t l;
sldns_buffer_clear(buf);
if((l=recv(fd, (void*)sldns_buffer_begin(buf),
if((l=recv(fd, (void*)sldns_buffer_begin(buf),
sldns_buffer_capacity(buf), 0)) < 0) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
printf("read data: %s\n",
printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@ -324,17 +347,40 @@ static int get_random(void)
return (int)arc4random();
}
/* parse the pp2_client and populate the proxy_buffer
* It doesn't populate the destination parts. */
static int parse_pp2_client(const char* pp2_client, int udp,
sldns_buffer* proxy_buf)
{
struct sockaddr_storage pp2_addr;
socklen_t pp2_addrlen = 0;
memset(&pp2_addr, 0, sizeof(pp2_addr));
if(*pp2_client == 0) return 0;
if(!extstrtoaddr(pp2_client, &pp2_addr, &pp2_addrlen, UNBOUND_DNS_PORT)) {
printf("fatal: bad proxy client specs '%s'\n", pp2_client);
exit(1);
}
sldns_buffer_clear(proxy_buf);
pp2_write_to_buf(proxy_buf, &pp2_addr, !udp);
sldns_buffer_flip(proxy_buf);
return 1;
}
/** send the TCP queries and print answers */
static void
send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
int delay, int num, char** qs)
send_em(const char* svr, const char* pp2_client, int udp, int usessl,
int noanswer, int onarrival, int delay, int num, char** qs)
{
sldns_buffer* buf = sldns_buffer_new(65553);
int fd = open_svr(svr, udp);
int i, wait_results = 0;
sldns_buffer* proxy_buf = sldns_buffer_new(65553);
struct sockaddr_storage svr_addr;
socklen_t svr_addrlen;
int fd = open_svr(svr, udp, &svr_addr, &svr_addrlen);
int i, wait_results = 0, pp2_parsed;
SSL_CTX* ctx = NULL;
SSL* ssl = NULL;
if(!buf) fatal_exit("out of memory");
pp2_parsed = parse_pp2_client(pp2_client, udp, proxy_buf);
if(usessl) {
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
if(!ctx) fatal_exit("cannot create ssl ctx");
@ -361,6 +407,28 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
}
}
/* Send the PROXYv2 information once per stream */
if(!udp && pp2_parsed) {
if(ssl) {
if(SSL_write(ssl, (void*)sldns_buffer_begin(proxy_buf),
(int)sldns_buffer_limit(proxy_buf)) <= 0) {
log_crypto_err("cannot SSL_write");
exit(1);
}
} else {
if(send(fd, (void*)sldns_buffer_begin(proxy_buf),
sldns_buffer_limit(proxy_buf), 0) <
(ssize_t)sldns_buffer_limit(proxy_buf)) {
#ifndef USE_WINSOCK
perror("send() data failed");
#else
printf("send data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
}
for(i=0; i<num; i+=3) {
if (delay != 0) {
#ifdef HAVE_SLEEP
@ -370,8 +438,9 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
#endif
}
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
qs[i+1], qs[i+2]);
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), proxy_buf,
pp2_parsed,
qs[i], qs[i+1], qs[i+2]);
/* print at least one result */
if(onarrival) {
wait_results += 1; /* one more answer to fetch */
@ -390,6 +459,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
sock_close(fd);
sldns_buffer_free(buf);
sldns_buffer_free(proxy_buf);
printf("orderly exit\n");
}
@ -418,10 +488,11 @@ extern int optind;
extern char* optarg;
/** main program for streamtcp */
int main(int argc, char** argv)
int main(int argc, char** argv)
{
int c;
const char* svr = "127.0.0.1";
const char* pp2_client = "";
int udp = 0;
int noanswer = 0;
int onarrival = 0;
@ -451,11 +522,14 @@ int main(int argc, char** argv)
if(argc == 1) {
usage(argv);
}
while( (c=getopt(argc, argv, "af:hnsud:")) != -1) {
while( (c=getopt(argc, argv, "af:p:hnsud:")) != -1) {
switch(c) {
case 'f':
svr = optarg;
break;
case 'p':
pp2_client = optarg;
break;
case 'a':
onarrival = 1;
break;
@ -508,7 +582,7 @@ int main(int argc, char** argv)
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
}
send_em(svr, udp, usessl, noanswer, onarrival, delay, argc, argv);
send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv);
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();

View File

@ -28,6 +28,12 @@ if grep "define UB_ON_WINDOWS 1" ../../config.h; then
else
onwin=0
fi
# detect dnscrypt
if grep "define USE_DNSCRYPT 1" ../../config.h; then
with_dnscrypt=1
else
with_dnscrypt=0
fi
# test check of config files.
for f in bad.*; do
@ -37,6 +43,10 @@ for f in bad.*; do
echo "skipped on windows"
continue
fi
if test $f = "bad.proxy-and-dnscrypt" -a $with_dnscrypt -eq 0; then
echo "skipped; no DNSCRYPT support"
continue
fi
$PRE/unbound-checkconf $f
if test $? != 1; then

View File

@ -0,0 +1,5 @@
server:
interface: 127.0.0.1
proxy-protocol-port: 53
dnscrypt:
dnscrypt-port: 53

View File

@ -0,0 +1,4 @@
server:
interface: 127.0.0.1
proxy-protocol-port: 53
https-port: 53

View File

@ -0,0 +1,34 @@
server:
verbosity: 5
num-threads: 1
interface: 127.0.0.1@@PORT@
interface: 127.0.0.1@@PROXYPORT@
interface: 127.0.0.1@@PROXYTLSPORT@
interface: @INTERFACE_ALLOW_ADDR@@@PORT@
interface: @INTERFACE_ALLOW_ADDR@@@PROXYPORT@
interface: @INTERFACE_ALLOW_ADDR@@@PROXYTLSPORT@
interface: @INTERFACE_REFUSE_ADDR@@@PORT@
interface: @INTERFACE_REFUSE_ADDR@@@PROXYPORT@
interface: @INTERFACE_REFUSE_ADDR@@@PROXYTLSPORT@
proxy-protocol-port: @PROXYPORT@
proxy-protocol-port: @PROXYTLSPORT@
tls-port: @PROXYTLSPORT@
use-syslog: no
directory: .
pidfile: "unbound.pid"
chroot: ""
username: ""
do-not-query-localhost: no
tls-service-key: "unbound_server.key"
tls-service-pem: "unbound_server.pem"
# 127.0.0.0/8 is allowed by default.
access-control: @CLIENT_ADDR_ALLOW@/32 allow
access-control: @CLIENT_ADDR_REFUSE@/32 refuse
access-control: @CLIENT_ADDR_ALLOW6@/128 allow
access-control: @CLIENT_ADDR_REFUSE6@/128 refuse
access-control: @INTERFACE_ALLOW_ADDR@/32 allow
forward-zone:
name: "."
forward-addr: "127.0.0.1@@TOPORT@"

View File

@ -0,0 +1,16 @@
BaseName: proxy_protocol
Version: 1.0
Description: Test proxy protocol
CreationDate: Mon Mar 14 16:17:00 CET 2022
Maintainer: Yorgos Thessalonikefs
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: proxy_protocol.pre
Post: proxy_protocol.post
Test: proxy_protocol.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,12 @@
# #-- proxy_protocol.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
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
. ../common.sh
kill_pid $FWD_PID
kill_pid $UNBOUND_PID
cat unbound.log
exit 0

View File

@ -0,0 +1,66 @@
# #-- proxy_protocol.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
PRE="../.."
. ../common.sh
# This test uses the unshare utility
if test ! -x "`which unshare 2>&1`"; then
skip_test "no unshare (from util-linux package) available, skip test"
fi
get_make
(cd $PRE; $MAKE streamtcp)
get_random_port 4
UNBOUND_PORT=$RND_PORT
FWD_PORT=$(($RND_PORT + 1))
PROXY_PORT=$(($RND_PORT + 2))
PROXY_TLS_PORT=$(($RND_PORT + 3))
INTERFACE_ALLOW=eth123
INTERFACE_ALLOW_ADDR=10.1.2.3
INTERFACE_REFUSE=eth234
INTERFACE_REFUSE_ADDR=10.2.3.4
CLIENT_ADDR_ALLOW=1.2.3.4
CLIENT_ADDR_ALLOW6=2001:db8::cafe:cafe
CLIENT_ADDR_REFUSE=5.6.7.8
CLIENT_ADDR_REFUSE6=2001:db8::dead:beef
# make config file
sed \
-e 's/@PORT\@/'$UNBOUND_PORT'/' \
-e 's/@TOPORT\@/'$FWD_PORT'/' \
-e 's/@PROXYPORT\@/'$PROXY_PORT'/' \
-e 's/@PROXYTLSPORT\@/'$PROXY_TLS_PORT'/' \
-e 's/@INTERFACE_ALLOW_ADDR\@/'$INTERFACE_ALLOW_ADDR'/' \
-e 's/@INTERFACE_REFUSE_ADDR\@/'$INTERFACE_REFUSE_ADDR'/' \
-e 's/@CLIENT_ADDR_ALLOW\@/'$CLIENT_ADDR_ALLOW'/' \
-e 's/@CLIENT_ADDR_ALLOW6\@/'$CLIENT_ADDR_ALLOW6'/' \
-e 's/@CLIENT_ADDR_REFUSE\@/'$CLIENT_ADDR_REFUSE'/' \
-e 's/@CLIENT_ADDR_REFUSE6\@/'$CLIENT_ADDR_REFUSE6'/' \
< proxy_protocol.conf > ub.conf
if test -x "`which bash`"; then
shell="bash"
else
shell="sh"
fi
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
echo "PROXY_PORT=$PROXY_PORT" >> .tpkg.var.test
echo "PROXY_TLS_PORT=$PROXY_TLS_PORT" >> .tpkg.var.test
echo "INTERFACE_ALLOW=$INTERFACE_ALLOW" >> .tpkg.var.test
echo "INTERFACE_ALLOW_ADDR=$INTERFACE_ALLOW_ADDR" >> .tpkg.var.test
echo "INTERFACE_REFUSE=$INTERFACE_REFUSE" >> .tpkg.var.test
echo "INTERFACE_REFUSE_ADDR=$INTERFACE_REFUSE_ADDR" >> .tpkg.var.test
echo "CLIENT_ADDR_ALLOW=$CLIENT_ADDR_ALLOW" >> .tpkg.var.test
echo "CLIENT_ADDR_ALLOW6=$CLIENT_ADDR_ALLOW6" >> .tpkg.var.test
echo "CLIENT_ADDR_REFUSE=$CLIENT_ADDR_REFUSE" >> .tpkg.var.test
echo "CLIENT_ADDR_REFUSE6=$CLIENT_ADDR_REFUSE6" >> .tpkg.var.test
echo "shell=$shell" >> .tpkg.var.test

View File

@ -0,0 +1,12 @@
# #-- proxy_protocol.test --#
# 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
PRE="../.."
. ../common.sh
# Run the scenario in an unshared namespace
unshare -rUn $shell proxy_protocol.test.scenario
exit $?

View File

@ -0,0 +1,193 @@
# #-- proxy_protocol.test.scenario --#
# 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
PRE="../.."
. ../common.sh
ip addr add 127.0.0.1 dev lo
ip link set lo up
ip link add $INTERFACE_ALLOW type dummy
ip addr add $INTERFACE_ALLOW_ADDR dev $INTERFACE_ALLOW
ip link set $INTERFACE_ALLOW up
ip link add $INTERFACE_REFUSE type dummy
ip addr add $INTERFACE_REFUSE_ADDR dev $INTERFACE_REFUSE
ip link set $INTERFACE_REFUSE up
# start forwarder in the background
get_ldns_testns
$LDNS_TESTNS -p $FWD_PORT proxy_protocol.testns >fwd.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
# start unbound in the background
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd.log
wait_unbound_up unbound.log
# call streamtcp and check return value
do_streamtcp () {
$PRE/streamtcp $* A IN >outfile 2>&1
if test "$?" -ne 0; then
echo "exit status not OK"
echo "> cat logfiles"
cat outfile
cat unbound.log
echo "Not OK"
exit 1
fi
}
send_query () {
server=$1
client=$2
prot=$3
query=$4
echo -n "> query $query to $server"
port=$UNBOUND_PORT
if test ! -z "$client"; then
port=$PROXY_PORT
fi
case $prot in
-u)
echo -n " (over UDP)"
;;
-s)
echo -n " (over TLS)"
port=$PROXY_TLS_PORT
;;
*)
echo -n " (over TCP)"
esac
if test ! -z "$client"; then
echo -n " ($client proxied)"
fi
echo
do_streamtcp $prot -f $server@$port $client $query
#cat outfile
}
expect_answer () {
#query=$1
#answer=$2
if grep "$query" outfile | grep "$answer"; then
echo "content OK"
echo
else
echo "> cat logfiles"
cat outfile
cat unbound.log
echo "result contents not OK"
exit 1
fi
}
expect_refuse () {
if grep "rcode: REFUSE" outfile; then
echo "content OK"
echo
else
echo "> cat logfiles"
cat outfile
cat unbound.log
echo "result contents not OK"
exit 1
fi
}
# Start the test
# Query without PROXYv2
# Client localhost
# Expect the result back
server=127.0.0.1
client=""
query="two.example.net."
answer="2.2.2.2"
for prot in "-u" ""; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW should be allowed
# Expect the result back
server=127.0.0.1
client="-p $CLIENT_ADDR_ALLOW@1234"
query="one.example.net."
answer="1.1.1.1"
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW6 should be allowed
# Expect the result back
server=127.0.0.1
client="-p $CLIENT_ADDR_ALLOW6@1234"
query="one.example.net."
answer="1.1.1.1"
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_REFUSE should be refused
# Expect the REFUSE back
server=127.0.0.1
client="-p $CLIENT_ADDR_REFUSE"
query="one.example.net."
answer=""
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_refuse
done
# Query with PROXYv2
# Client $CLIENT_ADDR_REFUSE6 should be refused
# Expect the REFUSE back
server=127.0.0.1
client="-p $CLIENT_ADDR_REFUSE6"
query="one.example.net."
answer=""
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_refuse
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW should be allowed; proxy source address should be allowed
# Expect the result back
server=$INTERFACE_ALLOW_ADDR
client="-p $CLIENT_ADDR_ALLOW@1234"
query="one.example.net."
answer="1.1.1.1"
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_answer
done
# Query with PROXYv2
# Client $CLIENT_ADDR_ALLOW should be allowed; proxy source address should be refused
# Expect the REFUSE back
server=$INTERFACE_REFUSE_ADDR
client="-p $CLIENT_ADDR_ALLOW@1234"
query="one.example.net."
answer=""
for prot in "-u" "" "-s"; do
send_query "$server" "$client" "$prot" "$query"
expect_refuse
done
echo "OK"
exit 0

View File

@ -0,0 +1,23 @@
; nameserver test file
$ORIGIN example.net.
$TTL 3600
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR RD RA NOERROR
ADJUST copy_id
SECTION QUESTION
one IN A
SECTION ANSWER
one IN A 1.1.1.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR RD RA NOERROR
ADJUST copy_id
SECTION QUESTION
two IN A
SECTION ANSWER
two IN A 2.2.2.2
ENTRY_END

View File

@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG5AIBAAKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI
0x41iG32a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+Nqq
GRS7XVQ24vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Z
uh9MDgotaBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8K
WaBe1ca4TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5
FzUReSXZuTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xP
q6O9UPj4+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XL
A5UoZgRzXgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP
7kFZSngxdy1+A/bNAgMBAAECggGBALpTOIqQwVg4CFBylL/a8K1IWJTI/I65sklf
XxYL7G7SB2HlEJ//z+E+F0+S4Vlao1vyLQ5QkgE82pAUB8FoMWvY1qF0Y8A5wtm6
iZSGk4OLK488ZbT8Ii9i+AGKgPe2XbVxsJwj8N4k7Zooqec9hz73Up8ATEWJkRz7
2u7oMGG4z91E0PULA64dOi3l/vOQe5w/Aa+CwVbAWtI05o7kMvQEBMDJn6C7CByo
MB5op9wueJMnz7PM7hns+U7Dy6oE4ljuolJUy51bDzFWwoM54cRoQqLFNHd8JVQj
WxldCkbfF43iyprlsEcUrTyUjtdA+ZeiG39vg/mtdmgNpGmdupHJZQvSuG8IcVlz
O+eMSeQS1QXPD6Ik8UK4SU0h+zOl8xIWtRrsxQuh4fnTN40udm/YUWl/6gOebsBI
IrVLlKGqJSfB3tMjpCRqdTzJ0dA9keVpkqm2ugZkxEf1+/efq/rFIQ2pUBLCqNTN
qpNqruK8y8FphP30I2uI4Ej2UIB8AQKBwQDd2Yptj2FyDyaXCycsyde0wYkNyzGU
dRnzdibfHnMZwjgTjwAwgIUBVIS8H0/z7ZJQKN7osJfddMrtjJtYYUk9g/dCpHXs
bNh2QSoWah3FdzNGuWd0iRf9+LFxhjAAMo/FS8zFJAJKrFsBdCGTfFUMdsLC0bjr
YjiWBuvV72uKf8XIZX5KIZruKdWBBcWukcb21R1UDyFYyXRBsly5XHaIYKZql3km
7pV7MKWO0IYgHbHIqGUqPQlzZ/lkunS1jKECgcEA23wHffD6Ou9/x3okPx2AWpTr
gh8rgqbyo6hQkBW5Y90Wz824cqaYebZDaBR/xlVx/YwjKkohv8Bde2lpH/ZxRZ1Z
5Sk2s6GJ/vU0L9RsJZgCgj4L6Coal1NMxuZtCXAlnOpiCdxSZgfqbshbTVz30KsG
ZJG361Cua1ScdAHxlZBxT52/1Sm0zRC2hnxL7h4qo7Idmtzs40LAJvYOKekR0pPN
oWeJfra7vgx/jVNvMFWoOoSLpidVO4g+ot4ery6tAoHAdW3rCic1C2zdnmH28Iw+
s50l8Lk3mz+I5wgJd1zkzCO0DxZIoWPGA3g7cmCYr6N3KRsZMs4W9NAXgjpFGDkW
zYsG3K21BdpvkdjYcFjnPVjlOXB2RIc0vehf9Jl02wXoeCSxVUDEPcaRvWk9RJYx
ZpGOchUU7vNkxHURbIJ4yCzuAi9G8/Jp0dsu+kaV5tufF5SjG5WOrzKjaQsCbdN1
oqaWMCHRrTvov/Z2C+xwsptFOdN5CSyZzg6hQiI4GMlBAoHAXyb6KINcOEi0YMp3
BFXJ23tMTnEs78tozcKeipigcsbaqORK3omS+NEnj+uzKUzJyl4CsMbKstK2tFYS
mSTCHqgE3PBtIpsZtEqhgUraR8IK9GPpzZDTTl9ynZgwFTNlWw3RyuyVXF56J+T8
kCGJ3hEHCHqT/ZRQyX85BKIDFhA0z4tYKxWVqIFiYBNq56R0X9tMMmMs36mEnF93
7Ht6mowxTZQRa7nU0qOgeKh/P7ki4Zus3y+WJ+T9IqahLtlRAoHBAIhqMrcxSAB8
RpB9jukJlAnidw2jCMPgrFE8tP0khhVvGrXMldxAUsMKntDIo8dGCnG1KTcWDI0O
jepvSPHSsxVLFugL79h0eVIS5z4huW48i9xgU8VlHdgAcgEPIAOFcOw2BCu/s0Vp
O+MM/EyUOdo3NsibB3qc/GJI6iNBYS7AljYEVo6rXo5V/MZvZUF4vClen6Obzsre
MTTb+4sJjfqleWuvr1XNMeu2mBfXBQkWGZP1byBK0MvD/aQ2PWq92A==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqzCCAhMCFBHWXeQ6ZIa9QcQbXLFfC6tj+KA+MA0GCSqGSIb3DQEBCwUAMBIx
EDAOBgNVBAMMB3VuYm91bmQwHhcNMjAwNzA4MTMzMjI5WhcNNDAwMzI1MTMzMjI5
WjASMRAwDgYDVQQDDAd1bmJvdW5kMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
igKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI0x41iG32
a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+NqqGRS7XVQ2
4vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Zuh9MDgot
aBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8KWaBe1ca4
TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5FzUReSXZ
uTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xPq6O9UPj4
+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XLA5UoZgRz
XgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP7kFZSngx
dy1+A/bNAgMBAAEwDQYJKoZIhvcNAQELBQADggGBABunf93MKaCUHiZgnoOTinsW
84/EgInrgtKzAyH+BhnKkJOhhR0kkIAx5d9BpDlaSiRTACFon9moWCgDIIsK/Ar7
JE0Kln9cV//wiiNoFU0O4mnzyGUIMvlaEX6QHMJJQYvL05+w/3AAcf5XmMJtR5ca
fJ8FqvGC34b2WxX9lTQoyT52sRt+1KnQikiMEnEyAdKktMG+MwKsFDdOwDXyZhZg
XZhRrfX3/NVJolqB6EahjWIGXDeKuSSKZVtCyib6LskyeMzN5lcRfvubKDdlqFVF
qlD7rHBsKhQUWK/IO64mGf7y/de+CgHtED5vDvr/p2uj/9sABATfbrOQR3W/Of25
sLBj4OEfrJ7lX8hQgFaxkMI3x6VFT3W8dTCp7xnQgb6bgROWB5fNEZ9jk/gjSRmD
yIU+r0UbKe5kBk/CmZVFXL2TyJ92V5NYEQh8V4DGy19qZ6u/XKYyNJL4ocs35GGe
CA8SBuyrmdhx38h1RHErR2Skzadi1S7MwGf1y431fQ==
-----END CERTIFICATE-----

View File

@ -786,6 +786,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_SIZET_NONZERO("pad-responses-block-size:", pad_responses_block_size)
else S_YNO("pad-queries:", pad_queries)
else S_SIZET_NONZERO("pad-queries-block-size:", pad_queries_block_size)
else S_STRLIST("proxy-protocol-port:", proxy_protocol_port)
#ifdef USE_IPSECMOD
else S_YNO("ipsecmod-enabled:", ipsecmod_enabled)
else S_YNO("ipsecmod-ignore-bogus:", ipsecmod_ignore_bogus)
@ -1262,6 +1263,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "pad-queries", pad_queries)
else O_DEC(opt, "pad-queries-block-size", pad_queries_block_size)
else O_LS2(opt, "edns-client-strings", edns_client_strings)
else O_LST(opt, "proxy-protocol-port", proxy_protocol_port)
#ifdef USE_IPSECMOD
else O_YNO(opt, "ipsecmod-enabled", ipsecmod_enabled)
else O_YNO(opt, "ipsecmod-ignore-bogus", ipsecmod_ignore_bogus)
@ -1642,6 +1644,7 @@ config_delete(struct config_file* cfg)
config_delstrlist(cfg->python_script);
config_delstrlist(cfg->dynlib_file);
config_deldblstrlist(cfg->edns_client_strings);
config_delstrlist(cfg->proxy_protocol_port);
#ifdef USE_IPSECMOD
free(cfg->ipsecmod_hook);
config_delstrlist(cfg->ipsecmod_whitelist);
@ -2624,3 +2627,35 @@ int cfg_has_https(struct config_file* cfg)
}
return 0;
}
/** see if interface is PROXYv2, its port number == the proxy port number */
int
if_is_pp2(const char* ifname, const char* port,
struct config_strlist* proxy_protocol_port)
{
struct config_strlist* s;
char* p = strchr(ifname, '@');
for(s = proxy_protocol_port; s; s = s->next) {
if(p && atoi(p+1) == atoi(s->str))
return 1;
if(!p && atoi(port) == atoi(s->str))
return 1;
}
return 0;
}
/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */
int
if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port)
{
#ifdef USE_DNSCRYPT
return ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
(!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
#else
(void)ifname;
(void)port;
(void)dnscrypt_port;
return 0;
#endif
}

View File

@ -114,6 +114,8 @@ struct config_file {
int do_tcp_keepalive;
/** tcp keepalive timeout, in msec */
int tcp_keepalive_timeout;
/** proxy protocol ports */
struct config_strlist* proxy_protocol_port;
/** private key file for dnstcp-ssl service (enabled if not NULL) */
char* ssl_service_key;
@ -1322,6 +1324,12 @@ int if_is_https(const char* ifname, const char* port, int https_port);
*/
int cfg_has_https(struct config_file* cfg);
/** see if interface is PROXYv2, its port number == the proxy port number */
int if_is_pp2(const char* ifname, const char* port,
struct config_strlist* proxy_protocol_port);
/** see if interface is DNSCRYPT, its port number == the dnscrypt port number */
int if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port);
#ifdef USE_LINUX_IP_LOCAL_PORT_RANGE
#define LINUX_IP_LOCAL_PORT_RANGE_PATH "/proc/sys/net/ipv4/ip_local_port_range"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -562,6 +562,7 @@ edns-client-string{COLON} { YDVAR(2, VAR_EDNS_CLIENT_STRING) }
edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) }
nsid{COLON} { YDVAR(1, VAR_NSID ) }
ede{COLON} { YDVAR(1, VAR_EDE ) }
proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */

File diff suppressed because it is too large Load Diff

View File

@ -383,7 +383,8 @@ extern int yydebug;
VAR_INTERFACE_VIEW = 584, /* VAR_INTERFACE_VIEW */
VAR_INTERFACE_TAG = 585, /* VAR_INTERFACE_TAG */
VAR_INTERFACE_TAG_ACTION = 586, /* VAR_INTERFACE_TAG_ACTION */
VAR_INTERFACE_TAG_DATA = 587 /* VAR_INTERFACE_TAG_DATA */
VAR_INTERFACE_TAG_DATA = 587, /* VAR_INTERFACE_TAG_DATA */
VAR_PROXY_PROTOCOL_PORT = 588 /* VAR_PROXY_PROTOCOL_PORT */
};
typedef enum yytokentype yytoken_kind_t;
#endif
@ -722,6 +723,7 @@ extern int yydebug;
#define VAR_INTERFACE_TAG 585
#define VAR_INTERFACE_TAG_ACTION 586
#define VAR_INTERFACE_TAG_DATA 587
#define VAR_PROXY_PROTOCOL_PORT 588
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@ -731,7 +733,7 @@ union YYSTYPE
char* str;
#line 735 "util/configparser.h"
#line 737 "util/configparser.h"
};
typedef union YYSTYPE YYSTYPE;

View File

@ -193,6 +193,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_RPZ_SIGNAL_NXDOMAIN_RA VAR_INTERFACE_AUTOMATIC_PORTS VAR_EDE
%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
%token VAR_PROXY_PROTOCOL_PORT
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -320,8 +321,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_edns_client_string_opcode | server_nsid |
server_zonemd_permissive_mode | server_max_reuse_tcp_queries |
server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
server_interface_automatic_ports | server_ede
server_interface_automatic_ports | server_ede |
server_proxy_protocol_port
;
stubstart: VAR_STUB_ZONE
{
@ -2824,6 +2825,13 @@ server_ede: VAR_EDE STRING_ARG
free($2);
}
;
server_proxy_protocol_port: VAR_PROXY_PROTOCOL_PORT STRING_ARG
{
OUTYY(("P(server_proxy_protocol_port:%s)\n", $2));
if(!cfg_strlist_insert(&cfg_parser->cfg->proxy_protocol_port, $2))
yyerror("out of memory");
}
;
stub_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));

File diff suppressed because it is too large Load Diff

View File

@ -128,10 +128,11 @@ struct comm_reply {
/** the comm_point with fd to send reply on to. */
struct comm_point* c;
/** the address (for UDP based communication) */
struct sockaddr_storage addr;
struct sockaddr_storage remote_addr;
/** length of address */
socklen_t addrlen;
/** return type 0 (none), 4(IP4), 6(IP6) */
socklen_t remote_addrlen;
/** return type 0 (none), 4(IP4), 6(IP6)
* used only with listen_type_udp_ancil* */
int srctype;
/* DnsCrypt context */
#ifdef USE_DNSCRYPT
@ -155,6 +156,13 @@ struct comm_reply {
pktinfo;
/** max udp size for udp packets */
size_t max_udp_size;
/* if set, the request came through a proxy */
int is_proxied;
/** the client address
* the same as remote_addr if not proxied */
struct sockaddr_storage client_addr;
/** the original address length */
socklen_t client_addrlen;
};
/**
@ -278,6 +286,19 @@ struct comm_point {
/** variable with type of socket, UDP,TCP-accept,TCP,pipe */
type;
/* -------- PROXYv2 ------- */
/** if set, PROXYv2 is expected on this connection */
int pp2_enabled;
/** header state for the PROXYv2 header (for TCP) */
enum {
/** no header encounter yet */
pp2_header_none = 0,
/** read the static part of the header */
pp2_header_init,
/** read the full header */
pp2_header_done
} pp2_header_state;
/* ---------- Behaviour ----------- */
/** if set the connection is NOT closed on delete. */
int do_not_close;
@ -496,8 +517,9 @@ struct ub_event_base* comm_base_internal(struct comm_base* b);
* Create an UDP comm point. Calls malloc.
* setups the structure with the parameters you provide.
* @param base: in which base to alloc the commpoint.
* @param fd : file descriptor of open UDP socket.
* @param fd: file descriptor of open UDP socket.
* @param buffer: shared buffer by UDP sockets from this thread.
* @param pp2_enabled: if the comm point will support PROXYv2.
* @param callback: callback function pointer.
* @param callback_arg: will be passed to your callback function.
* @param socket: and opened socket properties will be passed to your callback function.
@ -505,7 +527,7 @@ struct ub_event_base* comm_base_internal(struct comm_base* b);
* Sets timeout to NULL. Turns off TCP options.
*/
struct comm_point* comm_point_create_udp(struct comm_base* base,
int fd, struct sldns_buffer* buffer,
int fd, struct sldns_buffer* buffer, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket);
/**
@ -513,8 +535,9 @@ struct comm_point* comm_point_create_udp(struct comm_base* base,
* Uses recvmsg instead of recv to get udp message.
* setups the structure with the parameters you provide.
* @param base: in which base to alloc the commpoint.
* @param fd : file descriptor of open UDP socket.
* @param fd: file descriptor of open UDP socket.
* @param buffer: shared buffer by UDP sockets from this thread.
* @param pp2_enabled: if the comm point will support PROXYv2.
* @param callback: callback function pointer.
* @param callback_arg: will be passed to your callback function.
* @param socket: and opened socket properties will be passed to your callback function.
@ -522,7 +545,7 @@ struct comm_point* comm_point_create_udp(struct comm_base* base,
* Sets timeout to NULL. Turns off TCP options.
*/
struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
int fd, struct sldns_buffer* buffer,
int fd, struct sldns_buffer* buffer, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket);
/**
@ -544,6 +567,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* or NULL to not create those structures in the tcp handlers.
* @param port_type: the type of port we are creating a TCP listener for. Used
* to select handler type to use.
* @param pp2_enabled: if the comm point will support PROXYv2.
* @param callback: callback function pointer for TCP handlers.
* @param callback_arg: will be passed to your callback function.
* @param socket: and opened socket properties will be passed to your callback function.
@ -557,7 +581,7 @@ struct comm_point* comm_point_create_tcp(struct comm_base* base,
uint32_t http_max_streams, char* http_endpoint,
struct tcl_list* tcp_conn_limit,
size_t bufsize, struct sldns_buffer* spoolbuf,
enum listen_type port_type,
enum listen_type port_type, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket);
/**

139
util/proxy_protocol.c Normal file
View File

@ -0,0 +1,139 @@
/*
* util/proxy_protocol.c - event notification
*
* Copyright (c) 2022, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains PROXY protocol functions.
*/
#include "config.h"
#include "util/log.h"
#include "util/proxy_protocol.h"
int
pp2_write_to_buf(struct sldns_buffer* buf, struct sockaddr_storage* src,
int stream)
{
int af;
if(!src) return 0;
af = (int)((struct sockaddr_in*)src)->sin_family;
if(sldns_buffer_remaining(buf) <
PP2_HEADER_SIZE + (af==AF_INET?12:36)) {
return 0;
}
/* sig */
sldns_buffer_write(buf, PP2_SIG, PP2_SIG_LEN);
/* version and command */
sldns_buffer_write_u8(buf, (PP2_VERSION << 4) | PP2_CMD_PROXY);
if(af==AF_INET) {
/* family and protocol */
sldns_buffer_write_u8(buf,
(PP2_AF_INET<<4) |
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM));
/* length */
sldns_buffer_write_u16(buf, 12);
/* src addr */
sldns_buffer_write(buf,
&((struct sockaddr_in*)src)->sin_addr.s_addr, 4);
/* dst addr */
sldns_buffer_write_u32(buf, 0);
/* src port */
sldns_buffer_write(buf,
&((struct sockaddr_in*)src)->sin_port, 2);
/* dst port */
sldns_buffer_write_u16(buf, 0);
} else {
/* family and protocol */
sldns_buffer_write_u8(buf,
(PP2_AF_INET6<<4) |
(stream?PP2_PROT_STREAM:PP2_PROT_DGRAM));
/* length */
sldns_buffer_write_u16(buf, 36);
/* src addr */
sldns_buffer_write(buf,
&((struct sockaddr_in6*)src)->sin6_addr, 16);
/* dst addr */
sldns_buffer_set_at(buf,
sldns_buffer_position(buf), 0, 16);
sldns_buffer_skip(buf, 16);
/* src port */
sldns_buffer_write(buf,
&((struct sockaddr_in6*)src)->sin6_port, 2);
/* dst port */
sldns_buffer_write_u16(buf, 0);
}
return 1;
}
struct pp2_header*
pp2_read_header(struct sldns_buffer* buf)
{
size_t size;
struct pp2_header* header = (struct pp2_header*)sldns_buffer_begin(buf);
/* Try to fail all the unsupported cases first. */
if(sldns_buffer_remaining(buf) < PP2_HEADER_SIZE) {
log_err("proxy_protocol: not enough space for header");
return NULL;
}
/* Check for PROXYv2 header */
if(memcmp(header, PP2_SIG, PP2_SIG_LEN) != 0 ||
((header->ver_cmd & 0xF0)>>4) != PP2_VERSION) {
log_err("proxy_protocol: could not match PROXYv2 header");
return NULL;
}
/* Check the length */
size = PP2_HEADER_SIZE + ntohs(header->len);
if(sldns_buffer_remaining(buf) < size) {
log_err("proxy_protocol: not enough space for header");
return NULL;
}
/* Check for supported commands */
if((header->ver_cmd & 0xF) != PP2_CMD_LOCAL &&
(header->ver_cmd & 0xF) != PP2_CMD_PROXY) {
log_err("proxy_protocol: unsupported command");
return NULL;
}
/* Check for supported family and protocol */
if(header->fam_prot != 0x00 /* AF_UNSPEC|UNSPEC */ &&
header->fam_prot != 0x11 /* AF_INET|STREAM */ &&
header->fam_prot != 0x12 /* AF_INET|DGRAM */ &&
header->fam_prot != 0x21 /* AF_INET6|STREAM */ &&
header->fam_prot != 0x22 /* AF_INET6|DGRAM */) {
log_err("proxy_protocol: unsupported family and protocol");
return NULL;
}
/* We have a correct header */
return header;
}

131
util/proxy_protocol.h Normal file
View File

@ -0,0 +1,131 @@
/*
* util/proxy_protocol.h - PROXY protocol
*
* Copyright (c) 2022, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains PROXY protocol structs and functions.
* Only v2 is supported. TLVs are not currently supported.
*/
#ifndef PROXY_PROTOCOL_H
#define PROXY_PROTOCOL_H
#include "sldns/sbuffer.h"
/** PROXYv2 minimum header size */
#define PP2_HEADER_SIZE 16
/** PROXYv2 header signature */
#define PP2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
#define PP2_SIG_LEN 12
/** PROXYv2 version */
#define PP2_VERSION 0x2
/**
* PROXYv2 command.
*/
enum pp2_command {
PP2_CMD_LOCAL = 0x0,
PP2_CMD_PROXY = 0x1
};
/**
* PROXYv2 address family.
*/
enum pp2_af {
PP2_AF_UNSPEC = 0x0,
PP2_AF_INET = 0x1,
PP2_AF_INET6 = 0x2,
PP2_AF_UNIX = 0x3
};
/**
* PROXYv2 protocol.
*/
enum pp2_protocol {
PP2_PROT_UNSPEC = 0x0,
PP2_PROT_STREAM = 0x1,
PP2_PROT_DGRAM = 0x2
};
/**
* PROXYv2 header.
*/
struct pp2_header {
uint8_t sig[PP2_SIG_LEN];
uint8_t ver_cmd;
uint8_t fam_prot;
uint16_t len;
union {
struct { /* for TCP/UDP over IPv4, len = 12 */
uint32_t src_addr;
uint32_t dst_addr;
uint16_t src_port;
uint16_t dst_port;
} addr4;
struct { /* for TCP/UDP over IPv6, len = 36 */
uint8_t src_addr[16];
uint8_t dst_addr[16];
uint16_t src_port;
uint16_t dst_port;
} addr6;
struct { /* for AF_UNIX sockets, len = 216 */
uint8_t src_addr[108];
uint8_t dst_addr[108];
} addru;
} addr;
};
/**
* Write a PROXYv2 header at the current position of the buffer.
* @param buf: the buffer to write to.
* @param src: the source address.
* @param stream: if the protocol is stream or datagram.
* @return 1 on success, 0 on failure.
*/
int pp2_write_to_buf(struct sldns_buffer* buf, struct sockaddr_storage* src,
int stream);
/**
* Read a PROXYv2 header from the current position of the buffer.
* It does initial validation and returns a pointer to the buffer position on
* success.
* @param buf: the buffer to read from.
* @return the pointer to the buffer position on success, NULL on error.
*/
struct pp2_header* pp2_read_header(struct sldns_buffer* buf);
#endif /* PROXY_PROTOCOL_H */