diff options
author | mlaier <mlaier@FreeBSD.org> | 2004-06-16 23:26:00 +0000 |
---|---|---|
committer | mlaier <mlaier@FreeBSD.org> | 2004-06-16 23:26:00 +0000 |
commit | 6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e (patch) | |
tree | 91591a3c3277d8525d725da18322a0f9ba6078a2 /contrib/pf/authpf | |
parent | c9eda2a3d0e4116e5b63faaab29f4fe0695a4dad (diff) | |
download | FreeBSD-src-6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e.zip FreeBSD-src-6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e.tar.gz |
Import userland of pf 3.5 from OpenBSD (OPENBSD_3_5_BASE).
Diffstat (limited to 'contrib/pf/authpf')
-rw-r--r-- | contrib/pf/authpf/authpf.8 | 74 | ||||
-rw-r--r-- | contrib/pf/authpf/authpf.c | 138 |
2 files changed, 142 insertions, 70 deletions
diff --git a/contrib/pf/authpf/authpf.8 b/contrib/pf/authpf/authpf.8 index 141aecf..b6977da 100644 --- a/contrib/pf/authpf/authpf.8 +++ b/contrib/pf/authpf/authpf.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: authpf.8,v 1.30 2003/08/17 23:24:47 henning Exp $ +.\" $OpenBSD: authpf.8,v 1.31 2003/12/10 04:10:37 beck Exp $ .\" .\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved. .\" @@ -84,9 +84,9 @@ shared by all processes. By default, the .Pa anchor -name "authpf" is used, and the ruleset names equal the PIDs of the +name "authpf" is used, and the ruleset names equal the username and PID of the .Nm -processes. +processes as "username(pid)". The following rules need to be added to the main ruleset .Pa /etc/pf.conf in order to cause evaluation of any @@ -263,7 +263,8 @@ by creating an appropriate .Pa /etc/authpf/authpf.conf file. .Sh EXAMPLES -\fBControl Files\fP - To illustrate the user-specific access control +.Sy Control Files +\- To illustrate the user-specific access control mechanisms, let us consider a typical user named bob. Normally, as long as bob can authenticate himself, the .Nm @@ -298,7 +299,8 @@ file. Though bob is listed in the allow file, he is prevented from using this gateway due to the existence of a ban file. .Pp -\fBDistributed Authentication\fP - It is often desirable to interface with a +.Sy Distributed Authentication +\- It is often desirable to interface with a distributed password system rather than forcing the sysadmins to keep a large number of local password files in sync. The @@ -332,7 +334,8 @@ Using a default password file, all users will get as their shell except for root who will get .Pa /bin/csh . .Pp -\fBSSH Configuration\fP - As stated earlier, +.Sy SSH Configuration +\- As stated earlier, .Xr sshd 8 must be properly configured to detect and defeat network attacks. To that end, the following options should be added to @@ -346,7 +349,8 @@ ClientAliveCountMax 3 This ensures that unresponsive or spoofed sessions are terminated within a minute, since a hijacker should not be able to spoof ssh keepalive messages. .Pp -\fBBanners\fP - Once authenticated, the user is shown the contents of +.Sy Banners +\- Once authenticated, the user is shown the contents of .Pa /etc/authpf/authpf.message . This message may be a screen-full of the appropriate use policy, the contents of @@ -366,7 +370,8 @@ problem so we can fix it, please phone 1-900-314-1597 or send an email to remove@bulkmailerz.net. .Ed .Pp -\fBPacket Filter Rules\fP - In areas where this gateway is used to protect a +.Sy Packet Filter Rules +\- In areas where this gateway is used to protect a wireless network (a hub with several hundred ports), the default rule set as well as the per-user rules should probably allow very few things beyond encrypted protocols like @@ -378,15 +383,14 @@ On a securely switched network, with plug-in jacks for visitors who are given authentication accounts, you might want to allow out everything. In this context, a secure switch is one that tries to prevent address table overflow attacks. -The examples below assume a switched wired net. .Pp Example .Pa /etc/pf.conf : .Bd -literal # by default we allow internal clients to talk to us using # ssh and use us as a dns server. -internal_if=\&"fxp1\&" -gateway_addr=\&"10.0.1.1\&" +internal_if="fxp1" +gateway_addr="10.0.1.1" nat-anchor authpf rdr-anchor authpf binat-anchor authpf @@ -398,26 +402,28 @@ pass in quick on $internal_if proto udp from any to $gateway_addr \e anchor authpf .Ed .Pp -Example -.Pa /etc/authpf/authpf.rules : +.Sy For a switched, wired net +\- This example +.Pa /etc/authpf/authpf.rules +makes no real restrictions; it turns the IP address on and off, logging +TCP connections. .Bd -literal -# no real restrictions here, basically turn the network jack off or on. - -external_if = \&"xl0\&" -internal_if = \&"fxp0\&" +external_if = "xl0" +internal_if = "fxp0" pass in log quick on $internal_if proto tcp from $user_ip to any \e keep state pass in quick on $internal_if from $user_ip to any .Ed .Pp -Another example +.Sy For a wireless or shared net +\- This example .Pa /etc/authpf/authpf.rules -for an insecure network (such as a public wireless network) where +could be used for an insecure network (such as a public wireless network) where we might need to be a bit more restrictive. .Bd -literal -internal_if=\&"fxp1\&" -ipsec_gw=\&"10.2.3.4\&" +internal_if="fxp1" +ipsec_gw="10.2.3.4" # rdr ftp for proxying by ftp-proxy(8) rdr on $internal_if proto tcp from $user_ip to any port 21 \e @@ -433,6 +439,32 @@ pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e keep state pass in quick proto esp from $user_ip to $ipsec_gw .Ed +.Pp +.Sy Dealing with NAT +\- The following +.Pa /etc/authpf/authpf.rules +shows how to deal with NAT, using tags: +.Bd -literal +ext_if = "fxp1" +ext_addr = 129.128.11.10 +int_if = "fxp0" +# nat and tag connections... +nat on $ext_if from $user_ip to any tag $user_ip -> $ext_addr +pass in quick on $int_if from $user_ip to any +pass out log quick on $ext_if tagged $user_ip keep state +.Ed +.Pp +With the above rules added by +.Nm , +outbound connections corresponding to each users NAT'ed connections +will be logged as in the example below, where the user may be identified +from the ruleset name. +.Bd -literal +# tcpdump -n -e -ttt -i pflog0 +Oct 31 19:42:30.296553 rule 0.bbeck(20267).1/0(match): pass out on fxp1: \e +129.128.11.10.60539 > 198.137.240.92.22: S 2131494121:2131494121(0) win \e +16384 <mss 1460,nop,nop,sackOK> (DF) +.Ed .Sh FILES .Bl -tag -width "/etc/authpf/authpf.conf" -compact .It Pa /etc/authpf/authpf.conf diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c index 8828ffc..515cf8e 100644 --- a/contrib/pf/authpf/authpf.c +++ b/contrib/pf/authpf/authpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authpf.c,v 1.68 2003/08/21 19:13:23 frantzen Exp $ */ +/* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt Exp $ */ /* * Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org). @@ -46,6 +46,7 @@ #include <unistd.h> #include <pfctl_parser.h> +#include <pfctl.h> #include "pathnames.h" @@ -91,12 +92,6 @@ main(int argc, char *argv[]) char *cp; uid_t uid; - if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld", - (long)getpid())) < 0 || n >= sizeof(rulesetname)) { - syslog(LOG_ERR, "pid too large for ruleset name"); - exit(1); - } - config = fopen(PATH_CONFFILE, "r"); if ((cp = getenv("SSH_TTY")) == NULL) { @@ -124,7 +119,6 @@ main(int argc, char *argv[]) "cannot determine IP from SSH_CLIENT %s", ipsrc); exit(1); } - /* open the pf device */ dev = open(PATH_DEVFILE, O_RDWR); if (dev == -1) { @@ -153,6 +147,18 @@ main(int argc, char *argv[]) goto die; } + if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)", + luser, (long)getpid())) < 0 || n >= sizeof(rulesetname)) { + syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld", + luser, (long)getpid(), (long)getpid()); + if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld", + (long)getpid())) < 0 || n >= sizeof(rulesetname)) { + syslog(LOG_ERR, "pid too large for ruleset name"); + goto die; + } + } + + /* Make our entry in /var/authpf as /var/authpf/ipaddr */ n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc); if (n < 0 || (u_int)n >= sizeof(pidfile)) { @@ -235,15 +241,22 @@ main(int argc, char *argv[]) seteuid(getuid()); setuid(getuid()); - if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) + openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON); + + if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) { + syslog(LOG_INFO, "user %s prohibited", luser); do_death(0); + } - openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON); - if (config == NULL || read_config(config)) + if (config == NULL || read_config(config)) { + syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE); do_death(0); + } - if (remove_stale_rulesets()) + if (remove_stale_rulesets()) { + syslog(LOG_INFO, "error removing stale rulesets"); do_death(0); + } /* We appear to be making headway, so actually mark our pid */ rewind(pidfp); @@ -253,7 +266,7 @@ main(int argc, char *argv[]) if (change_filter(1, luser, ipsrc) == -1) { printf("Unable to modify filters\r\n"); - do_death(1); + do_death(0); } signal(SIGTERM, need_death); @@ -536,15 +549,20 @@ remove_stale_rulesets(void) mnr = prs.nr; nr = 0; while (nr < mnr) { - char *s; + char *s, *t; pid_t pid; prs.nr = nr; if (ioctl(dev, DIOCGETRULESET, &prs)) return (1); errno = 0; - pid = strtoul(prs.name, &s, 10); - if (!prs.name[0] || errno || *s) + if ((t = strchr(prs.name, '(')) == NULL) + t = prs.name; + else + t++; + pid = strtoul(t, &s, 10); + if (!prs.name[0] || errno || + (*s && (t == prs.name || *s != ')'))) return (1); if (kill(pid, 0) && errno != EPERM) { int i; @@ -576,14 +594,11 @@ change_filter(int add, const char *luser, const char *ipsrc) { char fn[MAXPATHLEN]; FILE *f = NULL; - const int action[PF_RULESET_MAX] = { PF_SCRUB, - PF_PASS, PF_NAT, PF_BINAT, PF_RDR }; struct pfctl pf; - struct pfioc_rule pr[PF_RULESET_MAX]; + struct pfr_buffer t; int i; - if (luser == NULL || !luser[0] || strlen(luser) >= - PF_RULESET_NAME_SIZE || ipsrc == NULL || !ipsrc[0]) { + if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) { syslog(LOG_ERR, "invalid luser/ipsrc"); goto error; } @@ -615,18 +630,18 @@ change_filter(int add, const char *luser, const char *ipsrc) syslog(LOG_ERR, "unable to load kernel's OS fingerprints"); goto error; } - + bzero(&t, sizeof(t)); + t.pfrb_type = PFRB_TRANS; memset(&pf, 0, sizeof(pf)); for (i = 0; i < PF_RULESET_MAX; ++i) { - memset(&pr[i], 0, sizeof(pr[i])); - pr[i].rule.action = action[i]; - strlcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor)); - strlcpy(pr[i].ruleset, rulesetname, sizeof(pr[i].ruleset)); - if (ioctl(dev, DIOCBEGINRULES, &pr[i])) { - syslog(LOG_ERR, "DIOCBEGINRULES %m"); + if (pfctl_add_trans(&t, i, anchorname, rulesetname)) { + syslog(LOG_ERR, "pfctl_add_trans %m"); goto error; } - pf.prule[i] = &pr[i]; + } + if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) { + syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove"); + goto error; } if (add) { @@ -637,6 +652,10 @@ change_filter(int add, const char *luser, const char *ipsrc) } pf.dev = dev; + pf.trans = &t; + pf.anchor = anchorname; + pf.ruleset = rulesetname; + infile = fn; if (parse_rules(f, &pf) < 0) { syslog(LOG_ERR, "syntax error in rule file: " @@ -649,16 +668,10 @@ change_filter(int add, const char *luser, const char *ipsrc) f = NULL; } - for (i = 0; i < PF_RULESET_MAX; ++i) - /* - * ignore EINVAL on removal, it means the anchor was - * already automatically removed by the kernel. - */ - if (ioctl(dev, DIOCCOMMITRULES, &pr[i]) && - (add || errno != EINVAL)) { - syslog(LOG_ERR, "DIOCCOMMITRULES %m"); - goto error; - } + if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) { + syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove"); + goto error; + } if (add) { gettimeofday(&Tstart, NULL); @@ -673,6 +686,8 @@ change_filter(int add, const char *luser, const char *ipsrc) error: if (f != NULL) fclose(f); + if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0)) + syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove"); infile = NULL; return (-1); @@ -748,37 +763,44 @@ do_death(int active) int pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) { - struct pfioc_rule *pr; + u_int8_t rs_num; + struct pfioc_rule pr; switch (r->action) { case PF_PASS: case PF_DROP: - pr = pf->prule[PF_RULESET_FILTER]; + rs_num = PF_RULESET_FILTER; break; case PF_SCRUB: - pr = pf->prule[PF_RULESET_SCRUB]; + rs_num = PF_RULESET_SCRUB; break; case PF_NAT: case PF_NONAT: - pr = pf->prule[PF_RULESET_NAT]; + rs_num = PF_RULESET_NAT; break; case PF_RDR: case PF_NORDR: - pr = pf->prule[PF_RULESET_RDR]; + rs_num = PF_RULESET_RDR; break; case PF_BINAT: case PF_NOBINAT: - pr = pf->prule[PF_RULESET_BINAT]; + rs_num = PF_RULESET_BINAT; break; default: syslog(LOG_ERR, "invalid rule action %d", r->action); return (1); } + + bzero(&pr, sizeof(pr)); + strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)); + strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)); if (pfctl_add_pool(pf, &r->rpool, r->af)) return (1); - pr->pool_ticket = pf->paddr.ticket; - memcpy(&pr->rule, r, sizeof(pr->rule)); - if (ioctl(pf->dev, DIOCADDRULE, pr)) { + pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor, + pf->ruleset); + pr.pool_ticket = pf->paddr.ticket; + memcpy(&pr.rule, r, sizeof(pr.rule)); + if (ioctl(pf->dev, DIOCADDRULE, &pr)) { syslog(LOG_ERR, "DIOCADDRULE %m"); return (1); } @@ -839,6 +861,13 @@ pfctl_set_logif(struct pfctl *pf, char *ifname) } int +pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) +{ + fprintf(stderr, "set hostid not supported in authpf\n"); + return (1); +} + +int pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) { fprintf(stderr, "set timeout not supported in authpf\n"); @@ -853,6 +882,13 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) } int +pfctl_set_debug(struct pfctl *pf, char *d) +{ + fprintf(stderr, "set debug not supported in authpf\n"); + return (1); +} + +int pfctl_define_table(char *name, int flags, int addrs, const char *anchor, const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) { @@ -862,10 +898,14 @@ pfctl_define_table(char *name, int flags, int addrs, const char *anchor, int pfctl_rules(int dev, char *filename, int opts, char *anchorname, - char *rulesetname) + char *rulesetname, struct pfr_buffer *t) { /* never called, no anchors inside anchors, but we need the stub */ fprintf(stderr, "load anchor not supported from authpf\n"); return (1); } +void +pfctl_print_title(char *title) +{ +} |