diff options
-rw-r--r-- | regress/sbin/pfctl/pf2.in | 2 | ||||
-rw-r--r-- | regress/sbin/pfctl/pf2.ok | 19 | ||||
-rw-r--r-- | sbin/pfctl/parse.y | 13 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 11 | ||||
-rw-r--r-- | share/man/man5/pf.conf.5 | 18 | ||||
-rw-r--r-- | sys/net/pf.c | 66 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 13 | ||||
-rw-r--r-- | sys/net/pfvar.h | 4 |
8 files changed, 114 insertions, 32 deletions
diff --git a/regress/sbin/pfctl/pf2.in b/regress/sbin/pfctl/pf2.in index ba509ebec67..2d1193167a9 100644 --- a/regress/sbin/pfctl/pf2.in +++ b/regress/sbin/pfctl/pf2.in @@ -17,6 +17,8 @@ block in log quick on tun0 from 172.16.0.0/12 to any block in log quick on tun0 from 192.168.0.0/16 to any block in log quick on tun0 from 255.255.255.255/32 to any +block in log quick from no-route to any + pass out on tun0 inet proto icmp all icmp-type 8 code 0 keep state pass in on tun0 inet proto icmp all icmp-type 8 code 0 keep state diff --git a/regress/sbin/pfctl/pf2.ok b/regress/sbin/pfctl/pf2.ok index 55f37414c8f..9842fbb21a3 100644 --- a/regress/sbin/pfctl/pf2.ok +++ b/regress/sbin/pfctl/pf2.ok @@ -10,12 +10,13 @@ @9 block in log quick on tun0 inet from 172.16.0.0/12 to any @10 block in log quick on tun0 inet from 192.168.0.0/16 to any @11 block in log quick on tun0 inet from 255.255.255.255/32 to any -@12 pass out on tun0 inet proto icmp all icmp-type echoreq code 0 keep state -@13 pass in on tun0 inet proto icmp all icmp-type echoreq code 0 keep state -@14 pass out on tun0 proto udp all keep state -@15 pass in on tun0 proto udp from any to any port = domain keep state -@16 pass out on tun0 proto tcp all keep state -@17 pass in on tun0 proto tcp from any to any port = ssh keep state -@18 pass in on tun0 proto tcp from any to any port = smtp keep state -@19 pass in on tun0 proto tcp from any to any port = domain keep state -@20 pass in on tun0 proto tcp from any to any port = auth keep state +@12 block in log quick from no-route to any +@13 pass out on tun0 inet proto icmp all icmp-type echoreq code 0 keep state +@14 pass in on tun0 inet proto icmp all icmp-type echoreq code 0 keep state +@15 pass out on tun0 proto udp all keep state +@16 pass in on tun0 proto udp from any to any port = domain keep state +@17 pass out on tun0 proto tcp all keep state +@18 pass in on tun0 proto tcp from any to any port = ssh keep state +@19 pass in on tun0 proto tcp from any to any port = smtp keep state +@20 pass in on tun0 proto tcp from any to any port = domain keep state +@21 pass in on tun0 proto tcp from any to any port = auth keep state diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index ad86add008c..9b186b68e4f 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.56 2002/02/27 18:11:45 dhartmei Exp $ */ +/* $OpenBSD: parse.y,v 1.57 2002/03/27 18:16:22 mickey Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -72,6 +72,7 @@ struct node_host { struct pf_addr mask; u_int8_t af; u_int8_t not; + u_int8_t noroute; struct node_host *next; }; @@ -171,6 +172,7 @@ typedef struct { %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF %token MINTTL IPV6ADDR ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO NO LABEL +%token NOROUTE %token <v.string> STRING %token <v.number> NUMBER %token <v.i> PORTUNARY PORTBINARY @@ -437,6 +439,12 @@ host_list : xhost { $$ = $1; } xhost : '!' host { $$ = $2; $$->not = 1; } | host { $$ = $1; } + | NOROUTE { + $$ = calloc(1, sizeof(struct node_host)); + if ($$ == NULL) + err(1, "xhost: calloc"); + $$->noroute = 1; + } ; host : address { @@ -1213,12 +1221,14 @@ void expand_rule_hosts(struct pf_rule *r, r->proto = proto->proto; r->src.addr = src_host->addr; r->src.mask = src_host->mask; + r->src.noroute = src_host->noroute; r->src.not = src_host->not; r->src.port[0] = src_port->port[0]; r->src.port[1] = src_port->port[1]; r->src.port_op = src_port->op; r->dst.addr = dst_host->addr; r->dst.mask = dst_host->mask; + r->dst.noroute = dst_host->noroute; r->dst.not = dst_host->not; r->dst.port[0] = dst_port->port[0]; r->dst.port[1] = dst_port->port[1]; @@ -1373,6 +1383,7 @@ lookup(char *s) { "nat", NAT}, { "no", NO}, { "no-df", NODF}, + { "no-route", NOROUTE}, { "on", ON}, { "out", OUT}, { "pass", PASS}, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index c9043f9b523..567683785d6 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.62 2002/03/12 08:15:03 dhartmei Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.63 2002/03/27 18:16:23 mickey Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -705,12 +705,15 @@ print_rule(struct pf_rule *r) } if (PF_AZERO(&r->src.addr, AF_INET6) && PF_AZERO(&r->src.mask, AF_INET6) && + !r->src.noroute && !r->dst.noroute && !r->src.port_op && PF_AZERO(&r->dst.addr, AF_INET6) && PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op) printf("all "); else { printf("from "); - if (PF_AZERO(&r->src.addr, AF_INET6) && + if (r->src.noroute) + printf("no-route "); + else if (PF_AZERO(&r->src.addr, AF_INET6) && PF_AZERO(&r->src.mask, AF_INET6)) printf("any "); else { @@ -725,7 +728,9 @@ print_rule(struct pf_rule *r) r->proto == IPPROTO_TCP ? "tcp" : "udp"); printf("to "); - if (PF_AZERO(&r->dst.addr, AF_INET6) && + if (r->dst.noroute) + printf("no-route "); + else if (PF_AZERO(&r->dst.addr, AF_INET6) && PF_AZERO(&r->dst.mask, AF_INET6)) printf("any "); else { diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index b63daaa5dc4..bcf6a82154f 100644 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pf.conf.5,v 1.35 2002/03/17 18:22:45 dhartmei Exp $ +.\" $OpenBSD: pf.conf.5,v 1.36 2002/03/27 18:16:17 mickey Exp $ .\" .\" Copyright (c) 2001, Daniel Hartmeier .\" All rights reserved. @@ -68,8 +68,8 @@ af = "inet" | "inet6" . proto-list = ( proto-name | proto-number ) [ "," proto-list ] . hosts = "all" | - "from" ( "any" | host | "{" host-list "}" ) [ port ] - "to" ( "any" | host | "{" host-list "}" ) [ port ] . + "from" ( "any" ! "no-route" | host | "{" host-list "}" ) [ port ] + "to" ( "any" | "no-route" | host | "{" host-list "}" ) [ port ] . host = [ "!" ] address [ "/" mask-bits ] . address = ( interface-name | host-name | ipv4-dotted-quad | @@ -219,7 +219,14 @@ The rule applies only to packets with the specified source and destination addresses/ports. .Pp Addresses can be specified in CIDR notation (matching netblocks), as -symbolic host names or interface names. +symbolic host names or interface names, or as any of the following keywords: +.Bl -tag -width no-route -compact +.It Em any +means any address; +.It Em no-route +means any address which is not currently routable. +.El +.Pp Host name resolution and interface to address translation are done at rule set load-time. When the address of an interface (or host name) changes (by DHCP or PPP, @@ -489,6 +496,9 @@ block return-rst in log on $ext_if proto tcp all block return-icmp out log on $ext_if proto udp all block return-icmp in log on $ext_if proto udp all +# block anything coming form source we have no back routes for +block in from no-route to any + # block and log outgoing packets that don't have our address as source, # they are either spoofed or something is misconfigured (NAT disabled, # for instance), we want to be nice and don't send out garbage. diff --git a/sys/net/pf.c b/sys/net/pf.c index e98c6a10e39..956d70a903b 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.197 2002/03/26 20:24:51 dhartmei Exp $ */ +/* $OpenBSD: pf.c,v 1.198 2002/03/27 18:16:21 mickey Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -2983,13 +2983,19 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp, r = r->skip[PF_SKIP_AF]; else if (r->proto && r->proto != IPPROTO_TCP) r = r->skip[PF_SKIP_PROTO]; - else if (!PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, + else if (r->src.noroute && pf_routable(saddr, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->src.noroute && + !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask, saddr, af)) r = r->skip[PF_SKIP_SRC_ADDR]; else if (r->src.port_op && !pf_match_port(r->src.port_op, r->src.port[0], r->src.port[1], th->th_sport)) r = r->skip[PF_SKIP_SRC_PORT]; - else if (!PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, + else if (r->dst.noroute && pf_routable(daddr, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->dst.noroute && + !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask, daddr, af)) r = r->skip[PF_SKIP_DST_ADDR]; else if (r->dst.port_op && !pf_match_port(r->dst.port_op, @@ -3209,14 +3215,20 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp, r = r->skip[PF_SKIP_AF]; else if (r->proto && r->proto != IPPROTO_UDP) r = r->skip[PF_SKIP_PROTO]; - else if (!PF_AZERO(&r->src.mask, af) && + else if (r->src.noroute && pf_routable(saddr, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->src.noroute && + !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask, saddr, af)) r = r->skip[PF_SKIP_SRC_ADDR]; else if (r->src.port_op && !pf_match_port(r->src.port_op, r->src.port[0], r->src.port[1], uh->uh_sport)) r = r->skip[PF_SKIP_SRC_PORT]; - else if (!PF_AZERO(&r->dst.mask, af) && + else if (r->dst.noroute && pf_routable(daddr, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->dst.noroute && + !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask, daddr, af)) r = r->skip[PF_SKIP_DST_ADDR]; @@ -3479,10 +3491,16 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp, r = r->skip[PF_SKIP_AF]; else if (r->proto && r->proto != pd->proto) r = r->skip[PF_SKIP_PROTO]; - else if (!PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, + else if (r->src.noroute && pf_routable(saddr, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->src.noroute && + !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask, saddr, af)) r = r->skip[PF_SKIP_SRC_ADDR]; - else if (!PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, + else if (r->dst.noroute && pf_routable(daddr, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->dst.noroute && + !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask, daddr, af)) r = r->skip[PF_SKIP_DST_ADDR]; else if (r->ifp != NULL && r->ifp != ifp) @@ -3682,10 +3700,16 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp, r = r->skip[PF_SKIP_AF]; else if (r->proto && r->proto != pd->proto) r = r->skip[PF_SKIP_PROTO]; - else if (!PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, + else if (r->src.noroute && pf_routable(pd->src, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->src.noroute && + !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask, pd->src, af)) r = r->skip[PF_SKIP_SRC_ADDR]; - else if (!PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, + else if (r->dst.noroute && pf_routable(pd->dst, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->src.noroute && + !PF_AZERO(&r->dst.mask, af) && !PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask, pd->dst, af)) r = r->skip[PF_SKIP_DST_ADDR]; else { @@ -4712,6 +4736,30 @@ pf_pull_hdr(struct mbuf *m, int off, void *p, int len, return (p); } +int +pf_routable(addr, af) + struct pf_addr *addr; + int af; +{ + struct sockaddr_in *dst; + struct route ro; + int ret = 0; + + bzero(&ro, sizeof(ro)); + dst = satosin(&ro.ro_dst); + dst->sin_family = af; + dst->sin_len = sizeof(*dst); + dst->sin_addr = addr->v4; + rtalloc_noclone(&ro, NO_CLONING); + + if (ro.ro_rt != NULL) { + ret = 1; + RTFREE(ro.ro_rt); + } + + return (ret); +} + #ifdef INET void pf_route(struct mbuf **m, struct pf_rule *r, int dir) diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c index 38de048815f..0436f6262c5 100644 --- a/sys/net/pf_norm.c +++ b/sys/net/pf_norm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.20 2002/02/26 07:25:33 dhartmei Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.21 2002/03/27 18:16:21 mickey Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -587,16 +587,19 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff, r = r->skip[PF_SKIP_AF]; else if (r->proto && r->proto != pd->proto) r = r->skip[PF_SKIP_PROTO]; - else if (!PF_AZERO(&r->src.mask, af) && + else if (r->src.noroute && pf_routable(pd->src, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->src.noroute && !PF_AZERO(&r->src.mask, af) && !PF_MATCHA(r->src.not, &r->src.addr, &r->src.mask, pd->src, af)) r = r->skip[PF_SKIP_SRC_ADDR]; else if (r->src.port_op && !pf_match_port(r->src.port_op, r->src.port[0], r->src.port[1], th->th_sport)) r = r->skip[PF_SKIP_SRC_PORT]; - else if (!PF_AZERO(&r->dst.mask, af) && - !PF_MATCHA(r->dst.not, - &r->dst.addr, &r->dst.mask, + else if (r->dst.noroute && pf_routable(pd->dst, af)) + r = TAILQ_NEXT(r, entries); + else if (!r->dst.noroute && !PF_AZERO(&r->dst.mask, af) && + !PF_MATCHA(r->dst.not, &r->dst.addr, &r->dst.mask, pd->dst, af)) r = r->skip[PF_SKIP_DST_ADDR]; else if (r->dst.port_op && !pf_match_port(r->dst.port_op, diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 051c40d2155..0c32f00293c 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.65 2002/03/25 22:03:01 frantzen Exp $ */ +/* $OpenBSD: pfvar.h,v 1.66 2002/03/27 18:16:21 mickey Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -187,6 +187,7 @@ struct pf_rule_addr { u_int16_t port[2]; u_int8_t not; u_int8_t port_op; + u_int8_t noroute; }; struct pf_rule { @@ -600,6 +601,7 @@ int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t); void pf_normalize_init(void); int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *); void pf_purge_expired_fragments(void); +int pf_routable(struct pf_addr *addr, int af); extern struct pf_rulequeue *pf_rules_active; extern struct pf_status pf_status; |