summaryrefslogtreecommitdiffstats
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorreyk <reyk@openbsd.org>2019-05-10 09:15:00 +0000
committerreyk <reyk@openbsd.org>2019-05-10 09:15:00 +0000
commit860302f3614d2aa36eb67596784e6e75ed2e8d4e (patch)
tree655a72a3a04d98f2e750c2fa515a40aab8d17d11 /usr.sbin/relayd
parentBackout latest, commited by mistake. (diff)
downloadwireguard-openbsd-860302f3614d2aa36eb67596784e6e75ed2e8d4e.tar.xz
wireguard-openbsd-860302f3614d2aa36eb67596784e6e75ed2e8d4e.zip
Add support for from/to in relay filter rules.
For example, pass from 10.0.0.0/8 path "/hello/*" forward to <b> Ok benno@
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r--usr.sbin/relayd/parse.y65
-rw-r--r--usr.sbin/relayd/relay.c48
-rw-r--r--usr.sbin/relayd/relay_http.c11
-rw-r--r--usr.sbin/relayd/relayd.conf.511
-rw-r--r--usr.sbin/relayd/relayd.h11
5 files changed, 105 insertions, 41 deletions
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index 2b1becc91e3..809c82cee3f 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.233 2019/03/13 23:29:32 benno Exp $ */
+/* $OpenBSD: parse.y,v 1.234 2019/05/10 09:15:00 reyk Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -153,6 +153,7 @@ typedef struct {
enum direction dir;
struct {
struct sockaddr_storage ss;
+ int prefixlen;
char name[HOST_NAME_MAX+1];
} addr;
struct {
@@ -187,7 +188,7 @@ typedef struct {
%type <v.number> action ruleaf key_option
%type <v.port> port
%type <v.host> host
-%type <v.addr> address
+%type <v.addr> address rulesrc ruledst addrprefix
%type <v.tv> timeout
%type <v.digest> digest optdigest
%type <v.table> tablespec
@@ -1293,6 +1294,20 @@ filterrule : action dir quick ruleaf rulesrc ruledst {
rule->rule_dir = $2;
rule->rule_flags |= $3;
rule->rule_af = $4;
+ rule->rule_src.addr = $5.ss;
+ rule->rule_src.addr_mask = $5.prefixlen;
+ rule->rule_dst.addr = $6.ss;
+ rule->rule_dst.addr_mask = $6.prefixlen;
+
+ if (RELAY_AF_NEQ(rule->rule_af,
+ rule->rule_src.addr.ss_family) ||
+ RELAY_AF_NEQ(rule->rule_af,
+ rule->rule_dst.addr.ss_family) ||
+ RELAY_AF_NEQ(rule->rule_src.addr.ss_family,
+ rule->rule_dst.addr.ss_family)) {
+ yyerror("address family mismatch");
+ YYERROR;
+ }
rulefile = NULL;
} ruleopts_l {
@@ -1341,10 +1356,20 @@ ruleaf : /* empty */ { $$ = AF_UNSPEC; }
| INET { $$ = AF_INET; }
;
-rulesrc : /* XXX */
+rulesrc : /* empty */ {
+ memset(&$$, 0, sizeof($$));
+ }
+ | FROM addrprefix {
+ $$ = $2;
+ }
;
-ruledst : /* XXX */
+ruledst : /* empty */ {
+ memset(&$$, 0, sizeof($$));
+ }
+ | TO addrprefix {
+ $$ = $2;
+ }
;
ruleopts_l : /* empty */
@@ -1967,7 +1992,7 @@ routeopts_l : routeopts_l routeoptsl nl
| routeoptsl optnl
;
-routeoptsl : ROUTE address '/' NUMBER {
+routeoptsl : ROUTE addrprefix {
struct netroute *nr;
if (router->rt_conf.af == AF_UNSPEC)
@@ -1978,14 +2003,6 @@ routeoptsl : ROUTE address '/' NUMBER {
YYERROR;
}
- if ((router->rt_conf.af == AF_INET &&
- ($4 > 32 || $4 < 0)) ||
- (router->rt_conf.af == AF_INET6 &&
- ($4 > 128 || $4 < 0))) {
- yyerror("invalid prefixlen %d", $4);
- YYERROR;
- }
-
if ((nr = calloc(1, sizeof(*nr))) == NULL)
fatal("out of memory");
@@ -1995,7 +2012,7 @@ routeoptsl : ROUTE address '/' NUMBER {
free(nr);
YYERROR;
}
- nr->nr_conf.prefixlen = $4;
+ nr->nr_conf.prefixlen = $2.prefixlen;
nr->nr_conf.routerid = router->rt_conf.id;
nr->nr_router = router;
bcopy(&$2.ss, &nr->nr_conf.ss, sizeof($2.ss));
@@ -2169,6 +2186,26 @@ address : STRING {
}
;
+addrprefix : address '/' NUMBER {
+ $$ = $1;
+ if (($$.ss.ss_family == AF_INET &&
+ ($3 > 32 || $3 < 0)) ||
+ ($$.ss.ss_family == AF_INET6 &&
+ ($3 > 128 || $3 < 0))) {
+ yyerror("invalid prefixlen %d", $3);
+ YYERROR;
+ }
+ $$.prefixlen = $3;
+ }
+ | address {
+ $$ = $1;
+ if ($$.ss.ss_family == AF_INET)
+ $$.prefixlen = 32;
+ else if ($$.ss.ss_family == AF_INET6)
+ $$.prefixlen = 128;
+ }
+ ;
+
retry : /* empty */ { $$ = 0; }
| RETRY NUMBER {
if (($$ = $2) < 0) {
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index 41bb8936caf..997a5f7a02b 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.243 2019/05/08 23:22:19 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.244 2019/05/10 09:15:00 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -28,6 +28,7 @@
#include <arpa/inet.h>
#include <limits.h>
+#include <netdb.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
@@ -117,6 +118,7 @@ relay_ruledebug(struct relay_rule *rule)
{
struct kv *kv = NULL;
u_int i;
+ char buf[NI_MAXHOST];
fprintf(stderr, "\t\t");
@@ -150,6 +152,25 @@ relay_ruledebug(struct relay_rule *rule)
if (rule->rule_flags & RULE_FLAG_QUICK)
fprintf(stderr, "quick ");
+ switch (rule->rule_af) {
+ case AF_INET:
+ fprintf(stderr, "inet ");
+ break;
+ case AF_INET6:
+ fprintf(stderr, "inet6 ");
+ break;
+ }
+
+ if (rule->rule_src.addr.ss_family != AF_UNSPEC)
+ fprintf(stderr, "from %s/%d ",
+ print_host(&rule->rule_src.addr, buf, sizeof(buf)),
+ rule->rule_src.addr_mask);
+
+ if (rule->rule_dst.addr.ss_family != AF_UNSPEC)
+ fprintf(stderr, "to %s/%d ",
+ print_host(&rule->rule_dst.addr, buf, sizeof(buf)),
+ rule->rule_dst.addr_mask);
+
for (i = 1; i < KEY_TYPE_MAX; i++) {
kv = &rule->rule_kv[i];
if (kv->kv_type != i)
@@ -1118,7 +1139,13 @@ relay_accept(int fd, short event, void *arg)
con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
break;
}
- bcopy(&ss, &con->se_in.ss, sizeof(con->se_in.ss));
+ memcpy(&con->se_in.ss, &ss, sizeof(con->se_in.ss));
+
+ slen = sizeof(con->se_sockname);
+ if (getsockname(s, (struct sockaddr *)&con->se_sockname, &slen) == -1) {
+ relay_close(con, "sockname lookup failed", 1);
+ return;
+ }
getmonotime(&con->se_tv_start);
bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last));
@@ -1143,12 +1170,8 @@ relay_accept(int fd, short event, void *arg)
}
if (rlay->rl_conf.flags & F_DIVERT) {
- slen = sizeof(con->se_out.ss);
- if (getsockname(s, (struct sockaddr *)&con->se_out.ss,
- &slen) == -1) {
- relay_close(con, "peer lookup failed", 1);
- return;
- }
+ memcpy(&con->se_out.ss, &con->se_sockname,
+ sizeof(con->se_out.ss));
con->se_out.port = relay_socket_getport(&con->se_out.ss);
/* Detect loop and fall back to the alternate forward target */
@@ -1169,13 +1192,8 @@ relay_accept(int fd, short event, void *arg)
cnl->proc = ps->ps_instance;
cnl->proto = IPPROTO_TCP;
- bcopy(&con->se_in.ss, &cnl->src, sizeof(cnl->src));
- slen = sizeof(cnl->dst);
- if (getsockname(s,
- (struct sockaddr *)&cnl->dst, &slen) == -1) {
- relay_close(con, "failed to get local address", 1);
- return;
- }
+ memcpy(&cnl->src, &con->se_in.ss, sizeof(cnl->src));
+ memcpy(&cnl->dst, &con->se_sockname, sizeof(cnl->dst));
proc_compose(env->sc_ps, PROC_PFE, IMSG_NATLOOK,
cnl, sizeof(*cnl));
diff --git a/usr.sbin/relayd/relay_http.c b/usr.sbin/relayd/relay_http.c
index f31c7e6e183..fb51ccb87a6 100644
--- a/usr.sbin/relayd/relay_http.c
+++ b/usr.sbin/relayd/relay_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay_http.c,v 1.73 2019/05/08 23:22:19 reyk Exp $ */
+/* $OpenBSD: relay_http.c,v 1.74 2019/05/10 09:15:00 reyk Exp $ */
/*
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -1765,13 +1765,12 @@ relay_test(struct protocol *proto, struct ctl_relay_event *cre)
RELAY_GET_SKIP_STEP(RULE_SKIP_DIR);
else if (proto->type != r->rule_proto)
RELAY_GET_SKIP_STEP(RULE_SKIP_PROTO);
- else if (r->rule_af != AF_UNSPEC &&
- (cre->ss.ss_family != r->rule_af ||
- cre->dst->ss.ss_family != r->rule_af))
+ else if (RELAY_AF_NEQ(r->rule_af, cre->ss.ss_family) ||
+ RELAY_AF_NEQ(r->rule_af, cre->dst->ss.ss_family))
RELAY_GET_SKIP_STEP(RULE_SKIP_AF);
else if (RELAY_ADDR_CMP(&r->rule_src, &cre->ss) != 0)
RELAY_GET_SKIP_STEP(RULE_SKIP_SRC);
- else if (RELAY_ADDR_CMP(&r->rule_dst, &cre->dst->ss) != 0)
+ else if (RELAY_ADDR_CMP(&r->rule_dst, &con->se_sockname) != 0)
RELAY_GET_SKIP_STEP(RULE_SKIP_DST);
else if (r->rule_method != HTTP_METHOD_NONE &&
(desc->http_method == HTTP_METHOD_RESPONSE ||
@@ -1870,7 +1869,7 @@ relay_calc_skip_steps(struct relay_rules *rules)
RELAY_SET_SKIP_STEPS(RULE_SKIP_DIR);
else if (cur->rule_proto != prev->rule_proto)
RELAY_SET_SKIP_STEPS(RULE_SKIP_PROTO);
- else if (cur->rule_af != prev->rule_af)
+ else if (RELAY_AF_NEQ(cur->rule_af, prev->rule_af))
RELAY_SET_SKIP_STEPS(RULE_SKIP_AF);
else if (RELAY_ADDR_NEQ(&cur->rule_src, &prev->rule_src))
RELAY_SET_SKIP_STEPS(RULE_SKIP_SRC);
diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5
index cab1657a7d1..ebfafc3f2de 100644
--- a/usr.sbin/relayd/relayd.conf.5
+++ b/usr.sbin/relayd/relayd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: relayd.conf.5,v 1.188 2019/03/04 21:25:03 benno Exp $
+.\" $OpenBSD: relayd.conf.5,v 1.189 2019/05/10 09:15:00 reyk Exp $
.\"
.\" Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
.\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 4 2019 $
+.Dd $Mdocdate: May 10 2019 $
.Dt RELAYD.CONF 5
.Os
.Sh NAME
@@ -1080,6 +1080,13 @@ evaluation is skipped.
.It Ic inet No or Ic inet6
Only match connections with the specified address family,
either of type IPv4 or IPv6.
+.It Ic from Ar address Ns Oo Li / Ns Ar prefix Oc
+This rule only matches for connections from the specified source.
+.It Ic to Ar address Ns Oo Li / Ns Ar prefix Oc
+This rule only matches for connections to the specified destination.
+The destination is the address the client was connecting to,
+typically the relay's listen address in non-transparent mode,
+not the address of the forwarded backend connection.
.It Ic forward to Pf < Ar table Ns >
Forward the request to a server in the specified table.
With this option, requests can be passed to specific backend servers.
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index 65ffe714aba..4f07ae1c9fe 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.253 2019/05/08 23:22:19 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.254 2019/05/10 09:15:00 reyk Exp $ */
/*
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -550,6 +550,7 @@ TAILQ_HEAD(rdrlist, rdr);
struct rsession {
objid_t se_id;
objid_t se_relayid;
+ struct sockaddr_storage se_sockname;
struct ctl_relay_event se_in;
struct ctl_relay_event se_out;
void *se_priv;
@@ -601,11 +602,9 @@ enum rule_action {
};
struct rule_addr {
- int addr_af;
struct sockaddr_storage addr;
u_int8_t addr_mask;
- int addr_net;
- in_port_t addr_port;
+ int addr_port;
};
#define RELAY_ADDR_EQ(_a, _b) \
@@ -622,6 +621,10 @@ struct rule_addr {
sockaddr_cmp((struct sockaddr *)&(_a)->addr, \
(struct sockaddr *)&(_b)->addr, (_a)->addr_mask) != 0)
+#define RELAY_AF_NEQ(_a, _b) \
+ (((_a) != AF_UNSPEC) && ((_b) != AF_UNSPEC) && \
+ ((_a) != (_b)))
+
struct relay_rule {
objid_t rule_id;
objid_t rule_protoid;