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 | a5725614a74c5e7e57dee0cda1a81ab91810a418 (patch) | |
tree | 4fec78418e07596814acd179ad425fa9253ec365 /contrib | |
parent | 5eba7986748fd69671d135d7c2e6c08545799d55 (diff) | |
parent | 6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e (diff) | |
download | FreeBSD-src-a5725614a74c5e7e57dee0cda1a81ab91810a418.zip FreeBSD-src-a5725614a74c5e7e57dee0cda1a81ab91810a418.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r130614,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/pf/authpf/authpf.8 | 74 | ||||
-rw-r--r-- | contrib/pf/ftp-proxy/util.c | 15 | ||||
-rw-r--r-- | contrib/pf/man/pf.conf.5 | 252 | ||||
-rw-r--r-- | contrib/pf/man/pf.os.5 | 4 | ||||
-rw-r--r-- | contrib/pf/pfctl/pf_print_state.c | 39 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl.8 | 138 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_osfp.c | 21 | ||||
-rw-r--r-- | contrib/pf/pfctl/pfctl_radix.c | 37 | ||||
-rw-r--r-- | contrib/pf/pflogd/pflogd.8 | 43 | ||||
-rw-r--r-- | contrib/pf/pflogd/pflogd.h | 47 | ||||
-rw-r--r-- | contrib/pf/pflogd/privsep.c | 305 | ||||
-rw-r--r-- | contrib/pf/pflogd/privsep_fdpass.c | 120 |
12 files changed, 925 insertions, 170 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/ftp-proxy/util.c b/contrib/pf/ftp-proxy/util.c index 3c8b20e..17a88ca 100644 --- a/contrib/pf/ftp-proxy/util.c +++ b/contrib/pf/ftp-proxy/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.16 2003/06/28 01:04:57 deraadt Exp $ */ +/* $OpenBSD: util.c,v 1.18 2004/01/22 16:10:30 beck Exp $ */ /* * Copyright (c) 1996-2001 @@ -58,6 +58,7 @@ int Debug_Level; int Use_Rdns; +in_addr_t Bind_Addr = INADDR_NONE; void debuglog(int debug_level, const char *fmt, ...); @@ -77,7 +78,8 @@ get_proxy_env(int connected_fd, struct sockaddr_in *real_server_sa_ptr, struct sockaddr_in *client_sa_ptr) { struct pfioc_natlook natlook; - int slen, fd; + socklen_t slen; + int fd; slen = sizeof(*real_server_sa_ptr); if (getsockname(connected_fd, (struct sockaddr *)real_server_sa_ptr, @@ -257,10 +259,13 @@ get_backchannel_socket(int type, int min_port, int max_port, int start_port, bzero(&sa, sizeof sa); sa.sin_family = AF_INET; - if (sap == NULL) - sa.sin_addr.s_addr = INADDR_ANY; + if (Bind_Addr == INADDR_NONE) + if (sap == NULL) + sa.sin_addr.s_addr = INADDR_ANY; + else + sa.sin_addr.s_addr = sap->sin_addr.s_addr; else - sa.sin_addr.s_addr = sap->sin_addr.s_addr; + sa.sin_addr.s_addr = Bind_Addr; /* * Indicate that we want to reuse a port if it happens that the diff --git a/contrib/pf/man/pf.conf.5 b/contrib/pf/man/pf.conf.5 index 9881318..b5db412 100644 --- a/contrib/pf/man/pf.conf.5 +++ b/contrib/pf/man/pf.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pf.conf.5,v 1.271 2003/09/02 18:37:08 jmc Exp $ +.\" $OpenBSD: pf.conf.5,v 1.292 2004/02/24 05:44:48 mcbride Exp $ .\" .\" Copyright (c) 2002, Daniel Hartmeier .\" All rights reserved. @@ -234,6 +234,9 @@ command. Interval between purging expired states and fragments. .It Ar frag Seconds before an unassembled fragment is expired. +.It Ar src.track +Length of time to retain a source tracking entry after the last state +expires. .El .Pp When a packet matches a stateful connection, the seconds to live for the @@ -366,10 +369,21 @@ sets the maximum number of entries in the memory pool used for fragment reassembly (generated by .Ar scrub rules) to 20000. +Finally, +.Bd -literal -offset indent +set limit src-nodes 2000 +.Ed +.Pp +sets the maximum number of entries in the memory pool used for tracking +source IP addresses (generated by the +.Ar sticky-address +and +.Ar source-track +options) to 2000. .Pp These can be combined: .Bd -literal -offset indent -set limit { states 20000, frags 20000 } +set limit { states 20000, frags 20000, src-nodes 2000 } .Ed .Pp .It Ar set optimization @@ -420,6 +434,24 @@ For example: .Bd -literal -offset indent set block-policy return .Ed +.It Ar set state-policy +The +.Ar state-policy +option sets the default behaviour for states: +.Pp +.Bl -tag -width group-bound -compact +.It Ar if-bound +States are bound to interface. +.It Ar group-bound +States are bound to interface group (i.e. ppp) +.It Ar floating +States can match packets on any interfaces (the default). +.El +.Pp +For example: +.Bd -literal -offset indent +set state-policy if-bound +.Ed .It Ar set require-order By default .Xr pfctl 8 @@ -450,6 +482,22 @@ ruleset finishes loading. For example: .Pp .Dl set fingerprints \&"/etc/pf.os.devel\&" +.Pp +.It Ar set debug +Set the debug +.Ar level +to one of the following: +.Pp +.Bl -tag -width xxxxxxxxxxxx -compact +.It Ar none +Don't generate debug messages. +.It Ar urgent +Generate debug messages only for serious errors. +.It Ar misc +Generate debug messages for various errors. +.It Ar loud +Generate debug messages for common conditions. +.El .El .Sh TRAFFIC NORMALIZATION Traffic normalization is used to sanitize packet content in such @@ -1092,15 +1140,17 @@ are specified, the rule will match packets in both directions. .It Ar log In addition to the action specified, a log message is generated. All packets for that connection are logged, unless the -.Ar keep state -or +.Ar keep state , .Ar modulate state +or +.Ar synproxy state options are specified, in which case only the packet that establishes the state is logged. (See -.Ar keep state -and +.Ar keep state , .Ar modulate state +and +.Ar synproxy state below). The logged packets are sent to the .Xr pflog 4 @@ -1114,9 +1164,10 @@ in binary format. .It Ar log-all Used with -.Ar keep state -or +.Ar keep state , .Ar modulate state +or +.Ar synproxy state rules to force logging of all packets for a connection. As with .Ar log , @@ -1131,6 +1182,8 @@ is skipped. .It Ar on <interface> This rule applies only to packets coming in on, or going out through, this particular interface. +It is also possible to simply give the interface driver name, like ppp or fxp, +to make the rule match packets flowing through a group of interfaces. .It Ar <af> This rule applies only to packets of this address family. Supported values are @@ -1175,14 +1228,24 @@ Interface names can have modifiers appended: Translates to the network(s) attached to the interface. .It Ar :broadcast Translates to the interface's broadcast address(es). +.It Ar :peer +Translates to the point to point interface's peer address(es). +.It Ar :0 +Do not include interface aliases. .El .Pp +Host names may also have the +.Ar :0 +option appended to restrict the name resolution to the first of each +v4 and v6 address found. +.Pp Host name resolution and interface to address translation are done at ruleset load-time. When the address of an interface (or host name) changes (under DHCP or PPP, for instance), the ruleset must be reloaded for the change to be reflected in the kernel. -Surrounding the interface name in parentheses changes this behaviour. +Surrounding the interface name (and optional modifiers) in parentheses +changes this behaviour. When the interface name is surrounded by parentheses, the rule is automatically updated whenever the interface changes its address. The ruleset does not need to be reloaded. @@ -1205,15 +1268,19 @@ Ports and ranges of ports are specified by using these operators: <= (less than or equal) > (greater than) >= (greater than or equal) ->< (range) +: (range including boundaries) +>< (range excluding boundaries) <> (except range) .Ed .Pp ->< and <> -are binary operators (they take two arguments), and the range -does not include the limits. +><, <> and : +are binary operators (they take two arguments). For instance: .Bl -tag -width Fl +.It Ar port 2000:2004 +means +.Sq all ports >= 2000 and <= 2004 , +hence ports 2000, 2001, 2002, 2003 and 2004. .It Ar port 2000 >< 2004 means .Sq all ports > 2000 and < 2004 , @@ -1421,13 +1488,17 @@ A packet is only ever assigned one tag at a time. rules that use the .Ar tag keyword must also use -.Ar keep state . +.Ar keep state , +.Ar modulate state +or +.Ar synproxy state . Packet tagging can be done during .Ar nat , .Ar rdr , or .Ar binat rules in addition to filter rules. +Tags take the same macros as labels (see above). .It Ar tagged <string> Used with filter rules to specify that packets must already be tagged with the given tag in order to match the rule. @@ -1533,6 +1604,23 @@ option prevents .Xr pf 4 from modifying the source port on TCP and UDP packets. .El +.Pp +Additionally, the +.Ar sticky-address +option can be specified to help ensure that multiple connections from the +same source are mapped to the same redirection address. +This option can be used with the +.Ar random +and +.Ar round-robin +pool options. +Note that by default these associations are destroyed as soon as there are +no longer states which refer to them; in order to make the mappings last +beyond the lifetime of the states, increase the global options with +.Ar set timeout source-track +See +.Sx STATEFUL TRACKING OPTIONS +for more ways to control the source tracking. .Sh STATEFUL INSPECTION .Xr pf 4 is a stateful packet filter, which means it can track the state of @@ -1579,6 +1667,37 @@ The initial packet of each connection has the SYN flag set, will be passed and creates state. All further packets of these connections are passed if they match a state. .Pp +By default, packets coming in and out of any interface can match a state, +but it is also possible to change that behaviour by assigning states to a +single interface or a group of interfaces. +.Pp +The default policy is specified by the +.Ar state-policy +global option, but this can be adjusted on a per-rule basis by adding one +of the +.Ar if-bound , +.Ar group-bound +or +.Ar floating +keywords to the +.Ar keep state +option. +For example, if a rule is defined as: +.Bd -literal -offset indent +pass out on ppp from any to 10.12/16 keep state (group-bound) +.Ed +.Pp +A state created on ppp0 would match packets an all PPP interfaces, +but not packets flowing through fxp0 or any other interface. +.Pp +Keeping rules +.Ar floating +is the more flexible option when the firewall is in a dynamic routing +environment. +However, this has some security implications since a state created by one +trusted network could allow potentially hostile packets coming in from other +interfaces. +.Pp Specifying .Ar flags S/SA restricts state creation to the initial SYN @@ -1695,7 +1814,7 @@ handshake. The proxy is transparent to both endpoints, they each see a single connection from/to the other endpoint. .Xr pf 4 -choses random initial sequence numbers for both handshakes. +chooses random initial sequence numbers for both handshakes. Once the handshakes are completed, the sequence number modulators (see previous section) are used to translate further packets of the connection. @@ -1730,8 +1849,26 @@ support the following options: Limits the number of concurrent states the rule may create. When this limit is reached, further packets matching the rule that would create state are dropped, until existing states time out. +.It Ar no-sync +Prevent state changes for states created by this rule from appearing on the +.Xr pfsync 4 +interface. .It Ar <timeout> <seconds> Changes the timeout values used for states created by this rule. +.Pp +When the +.Ar source-track +keyword is specified, the number of states per source IP is tracked. +The following limits can be set: +.Pp +.Bl -tag -width xxxx -compact +.It Ar max-src-nodes +Limits the maximum number of source addresses which can simultaneously +have state table entries. +.It Ar max-src-states +Limits the maximum number of simultaneous state entries that a single +source address can create with this rule. +.El For a list of all valid timeout names, see .Sx OPTIONS above. @@ -1740,7 +1877,8 @@ Multiple options can be specified, separated by commas: .Bd -literal pass in proto tcp from any to any \e port www flags S/SA keep state \e - (max 100, tcp.established 60, tcp.closing 5) + (max 100, source-track rule, max-src-nodes 75, \e + max-src-states 3, tcp.established 60, tcp.closing 5) .Ed .El .Sh OPERATING SYSTEM FINGERPRINTING @@ -1853,7 +1991,7 @@ to local addresses. One should pass these explicitly. .Sh FRAGMENT HANDLING The size of IP datagrams (packets) can be significantly larger than the -the maximum transmission unit (MTU) of the network. +maximum transmission unit (MTU) of the network. In cases when it is necessary or more efficient to send such large packets, the large packet will be fragmented into many smaller packets that will each fit onto the wire. @@ -2027,7 +2165,7 @@ rule after the rule: .Bd -literal -offset indent anchor spam -load anchor spam:manual from /etc/pf-spam.conf +load anchor spam:manual from "/etc/pf-spam.conf" .Ed .Pp When @@ -2072,8 +2210,11 @@ This example maps incoming requests on port 80 to port 8080, on which a daemon is running (because, for example, it is not run as root, and therefore lacks permission to bind to port 80). .Bd -literal +# use a macro for the interface name, so it can be changed easily +ext_if = \&"ne3\&" + # map daemon on 8080 to appear to be on 80 -rdr on ne3 proto tcp from any to any port 80 -> 127.0.0.1 port 8080 +rdr on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080 .Ed .Pp If the @@ -2081,7 +2222,8 @@ If the modifier is given, packets matching the translation rule are passed without inspecting the filter rules: .Bd -literal -rdr pass on ne3 proto tcp from any to any port 80 -> 127.0.0.1 port 8080 +rdr pass on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 \e + port 8080 .Ed .Pp In the example below, vlan12 is configured as 192.168.168.1; @@ -2096,83 +2238,80 @@ for the nodes on vlan12. nat on ! vlan12 from 192.168.168.0/24 to any -> 204.92.77.111 .Ed .Pp -In the example below, fxp1 is the outside interface; the machine sits between a -fake internal 144.19.74.* network, and a routable external IP of 204.92.77.100. +In the example below, the machine sits between a fake internal 144.19.74.* +network, and a routable external IP of 204.92.77.100. The .Ar no nat rule excludes protocol AH from being translated. .Bd -literal # NO NAT -no nat on fxp1 proto ah from 144.19.74.0/24 to any -nat on fxp1 from 144.19.74.0/24 to any -> 204.92.77.100 +no nat on $ext_if proto ah from 144.19.74.0/24 to any +nat on $ext_if from 144.19.74.0/24 to any -> 204.92.77.100 .Ed .Pp -In the example below, fxp0 is the internal interface. -Packets bound -for one specific server, as well as those generated by the sysadmins -are not proxied; all other connections are. +In the example below, packets bound for one specific server, as well as those +generated by the sysadmins are not proxied; all other connections are. .Bd -literal # NO RDR -no rdr on fxp0 proto { tcp, udp } from any to $server port 80 -no rdr on fxp0 proto { tcp, udp } from $sysadmins to any port 80 -rdr on fxp0 proto { tcp, udp } from any to any port 80 -> 127.0.0.1 port 80 +no rdr on $int_if proto { tcp, udp } from any to $server port 80 +no rdr on $int_if proto { tcp, udp } from $sysadmins to any port 80 +rdr on $int_if proto { tcp, udp } from any to any port 80 -> 127.0.0.1 \e + port 80 .Ed .Pp This longer example uses both a NAT and a redirection. -Interface kue0 is the outside interface, and its external address is -157.161.48.183. -Interface fxp0 is the inside interface, and we are running +The external interface has the address 157.161.48.183. +On the internal interface, we are running .Xr ftp-proxy 8 , listening for outbound ftp sessions captured to port 8021. .Bd -literal # NAT # Translate outgoing packets' source addresses (any protocol). # In this case, any address but the gateway's external address is mapped. -nat on kue0 inet from ! (kue0) to any -> (kue0) +nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if) # NAT PROXYING # Map outgoing packets' source port to an assigned proxy port instead of # an arbitrary port. # In this case, proxy outgoing isakmp with port 500 on the gateway. -nat on kue0 inet proto udp from any port = isakmp to any -> (kue0) \e +nat on $ext_if inet proto udp from any port = isakmp to any -> ($ext_if) \e port 500 # BINAT # Translate outgoing packets' source address (any protocol). # Translate incoming packets' destination address to an internal machine # (bidirectional). -binat on kue0 from 10.1.2.150 to any -> (kue0) +binat on $ext_if from 10.1.2.150 to any -> ($ext_if) # RDR # Translate incoming packets' destination addresses. # As an example, redirect a TCP and UDP port to an internal machine. -rdr on kue0 inet proto tcp from any to (kue0) port 8080 -> 10.1.2.151 \e - port 22 -rdr on kue0 inet proto udp from any to (kue0) port 8080 -> 10.1.2.151 \e - port 53 +rdr on $ext_if inet proto tcp from any to ($ext_if) port 8080 \e + -> 10.1.2.151 port 22 +rdr on $ext_if inet proto udp from any to ($ext_if) port 8080 \e + -> 10.1.2.151 port 53 # RDR # Translate outgoing ftp control connections to send them to localhost # for proxying with ftp-proxy(8) running on port 8021. -rdr on fxp0 proto tcp from any to any port 21 -> 127.0.0.1 port 8021 +rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021 .Ed .Pp In this example, a NAT gateway is set up to translate internal addresses using a pool of public addresses (192.0.2.16/28) and to redirect incoming web server connections to a group of web servers on the internal network. -Interface fxp0 is the external interface. .Bd -literal # NAT LOAD BALANCE # Translate outgoing packets' source addresses using an address pool. # A given source address is always translated to the same pool address by # using the source-hash keyword. -nat on fxp0 inet from any to any -> 192.0.2.16/28 source-hash +nat on $ext_if inet from any to any -> 192.0.2.16/28 source-hash # RDR ROUND ROBIN # Translate incoming web server connections to a group of web servers on # the internal network. -rdr on fxp0 proto tcp from any to any port 80 \e +rdr on $ext_if proto tcp from any to any port 80 \e -> { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin .Ed .Sh FILTER EXAMPLES @@ -2283,8 +2422,11 @@ option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] | [ "limit" ( limit-item | "{" limit-list "}" ) ] | [ "loginterface" ( interface-name | "none" ) ] | [ "block-policy" ( "drop" | "return" ) ] | + [ "state-policy" ( "if-bound" | "group-bound" | + "floating" ) ] [ "require-order" ( "yes" | "no" ) ] - [ "fingerprints" filename ] ) + [ "fingerprints" filename ] | + [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] ) pf-rule = action [ ( "in" | "out" ) ] [ "log" | "log-all" ] [ "quick" ] @@ -2299,7 +2441,7 @@ filteropt = user | group | flags | icmp-type | icmp6-type | tos | "max-mss" number | "random-id" | "reassemble tcp" | fragmentation | "allow-opts" | "label" string | "tag" string | [ ! ] "tagged" string - "queue" "(" string | ( string [ [ "," ] string ] ) ")" + "queue" ( string | "(" string [ [ "," ] string ] ")" ) nat-rule = [ "no" ] "nat" [ "pass" ] [ "on" ifspec ] [ af ] [ protospec ] hosts [ "tag" string ] @@ -2341,7 +2483,7 @@ anchor-rule = "anchor" string [ ( "in" | "out" ) ] [ "on" ifspec ] trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string [ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ] -load-anchor = "load" anchorname:rulesetname "from" filename +load-anchor = "load anchor" anchorname:rulesetname "from" filename queueopts-list = queueopts-list queueopts | queueopts queueopts = [ "bandwidth" bandwidth-spec ] | @@ -2350,7 +2492,7 @@ queueopts = [ "bandwidth" bandwidth-spec ] | schedulers = ( cbq-def | priq-def | hfsc-def ) bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" ) -action = "pass" | "block" [ "return" ] | "scrub" +action = "pass" | "block" [ return ] | "scrub" return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] | "return-icmp" [ "(" icmpcode ["," icmp6code ] ")" ] | "return-icmp6" [ "(" icmp6code ")" ] @@ -2413,7 +2555,10 @@ tos = "tos" ( "lowdelay" | "throughput" | "reliability" | [ "0x" ] number ) state-opts = state-opt [ [ "," ] state-opts ] -state-opt = ( "max" number ) | ( timeout ) +state-opt = ( "max" number | "no-sync" | timeout | + "source-track" [ ( "rule" | "global" ) ] | + "max-src-nodes" number | "max-src-states" number | + "if-bound" | "group-bound" | "floating" ) fragmentation = [ "fragment reassemble" | "fragment crop" | "fragment drop-ovl" ] @@ -2424,15 +2569,15 @@ timeout = ( "tcp.first" | "tcp.opening" | "tcp.established" | "udp.first" | "udp.single" | "udp.multiple" | "icmp.first" | "icmp.error" | "other.first" | "other.single" | "other.multiple" | - "frag" | "interval" | + "frag" | "interval" | "src.track" | "adaptive.start" | "adaptive.end" ) number limit-list = limit-item [ [ "," ] limit-list ] -limit-item = ( "states" | "frags" ) number +limit-item = ( "states" | "frags" | "src-nodes" ) number pooltype = ( "bitmask" | "random" | "source-hash" [ ( hex-key | string-key ) ] | - "round-robin" ) + "round-robin" ) [ sticky-address ] subqueue = string | "{" queue-list "}" queue-list = string [ [ "," ] string ] @@ -2470,6 +2615,7 @@ Example rulesets. .Xr ip 4 , .Xr ip6 4 , .Xr pf 4 , +.Xr pfsync 4 , .Xr tcp 4 , .Xr udp 4 , .Xr hosts 5 , diff --git a/contrib/pf/man/pf.os.5 b/contrib/pf/man/pf.os.5 index 485f69a..9978174 100644 --- a/contrib/pf/man/pf.os.5 +++ b/contrib/pf/man/pf.os.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pf.os.5,v 1.4 2003/08/28 09:41:23 jmc Exp $ +.\" $OpenBSD: pf.os.5,v 1.5 2003/10/25 07:55:27 jmc Exp $ .\" .\" Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org> .\" @@ -77,7 +77,7 @@ Allow any window size which is a multiple of the maximum transmission unit The .Ar ttl value is the initial time to live in the IP header. -The fingerprint code will account for the volatility of the packets's TTL +The fingerprint code will account for the volatility of the packet's TTL as it traverses a network. .Pp The diff --git a/contrib/pf/pfctl/pf_print_state.c b/contrib/pf/pfctl/pf_print_state.c index 58ce23a..b7cf5ca 100644 --- a/contrib/pf/pfctl/pf_print_state.c +++ b/contrib/pf/pfctl/pf_print_state.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_print_state.c,v 1.33 2003/07/06 22:01:28 deraadt Exp $ */ +/* $OpenBSD: pf_print_state.c,v 1.39 2004/02/10 17:48:08 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -50,9 +50,24 @@ void print_name(struct pf_addr *, sa_family_t); void print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose) { - switch(addr->type) { + switch (addr->type) { case PF_ADDR_DYNIFTL: - printf("(%s)", addr->v.ifname); + printf("(%s", addr->v.ifname); + if (addr->iflags & PFI_AFLAG_NETWORK) + printf(":network"); + if (addr->iflags & PFI_AFLAG_BROADCAST) + printf(":broadcast"); + if (addr->iflags & PFI_AFLAG_PEER) + printf(":peer"); + if (addr->iflags & PFI_AFLAG_NOALIAS) + printf(":0"); + if (verbose) { + if (addr->p.dyncnt <= 0) + printf(":*"); + else + printf(":%d", addr->p.dyncnt); + } + printf(")"); break; case PF_ADDR_TABLE: if (verbose) @@ -85,7 +100,10 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose) printf("?"); return; } - if (! PF_AZERO(&addr->v.a.mask, af)) { + + /* mask if not _both_ address and mask are zero */ + if (!(PF_AZERO(&addr->v.a.addr, AF_INET6) && + PF_AZERO(&addr->v.a.mask, AF_INET6))) { int bits = unmask(&addr->v.a.mask, af); if (bits != (af == AF_INET ? 32 : 128)) @@ -140,8 +158,10 @@ print_host(struct pf_state_host *h, sa_family_t af, int opts) aw.v.a.addr = h->addr; if (af == AF_INET) aw.v.a.mask.addr32[0] = 0xffffffff; - else + else { memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); + af = AF_INET6; + } print_addr(&aw, af, opts & PF_OPT_VERBOSE2); } @@ -177,6 +197,7 @@ print_state(struct pf_state *s, int opts) src = &s->dst; dst = &s->src; } + printf("%s ", s->u.ifname); if ((p = getprotobynumber(s->proto)) != NULL) printf("%s ", p->p_name); else @@ -256,8 +277,16 @@ print_state(struct pf_state *s, int opts) printf(", anchor %u", s->anchor.nr); if (s->rule.nr != -1) printf(", rule %u", s->rule.nr); + if (s->src_node != NULL) + printf(", source-track"); + if (s->nat_src_node != NULL) + printf(", sticky-address"); printf("\n"); } + if (opts & PF_OPT_VERBOSE2) { + printf(" id: %016llx creatorid: %08x\n", + betoh64(s->id), ntohl(s->creatorid)); + } } int diff --git a/contrib/pf/pfctl/pfctl.8 b/contrib/pf/pfctl/pfctl.8 index fb73ce2..6fac2d5 100644 --- a/contrib/pf/pfctl/pfctl.8 +++ b/contrib/pf/pfctl/pfctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pfctl.8,v 1.102 2003/09/18 09:18:51 jmc Exp $ +.\" $OpenBSD: pfctl.8,v 1.110 2004/03/20 09:31:42 david Exp $ .\" .\" Copyright (c) 2001 Kjell Wooding. All rights reserved. .\" @@ -33,15 +33,17 @@ .Sh SYNOPSIS .Nm pfctl .Bk -words -.Op Fl AdeghnNqrROvz +.Op Fl AdeghNnOqRrvz .Op Fl a Ar anchor Ns Op Ar :ruleset .Op Fl D Ar macro=value -.Op Fl f Ar file .Op Fl F Ar modifier +.Op Fl f Ar file +.Op Fl i Ar interface .Op Fl k Ar host +.Op Fl p Ar device .Op Fl s Ar modifier -.Op Fl t Ar table .Op Fl T Ar command Op Ar address ... +.Op Fl t Ar table .Op Fl x Ar level .Ek .Sh DESCRIPTION @@ -93,6 +95,9 @@ The utility provides several commands. The options are as follows: .Bl -tag -width Ds +.It Fl A +Load only the queue rules present in the rule file. +Other rules and options are ignored. .It Fl a Ar anchor Ns Op Ar :ruleset Apply flags .Fl f , @@ -134,11 +139,6 @@ This is similar to C rules for variables. It is possible to create distinct tables with the same name in the global ruleset and in an anchor, but this is often bad design and a warning will be issued in that case. -.It Fl A -Load only the queue rules present in the rule file. -Other rules and options are ignored. -.It Fl d -Disable the packet filter. .It Fl D Ar macro=value Define .Ar macro @@ -148,17 +148,10 @@ on the command line. Overrides the definition of .Ar macro in the ruleset. +.It Fl d +Disable the packet filter. .It Fl e Enable the packet filter. -.It Fl f Ar file -Load the rules contained in -.Ar file . -This -.Ar file -may contain macros, tables, options, and normalization, queueing, -translation, and filtering rules. -With the exception of macros and tables, the statements must appear in that -order. .It Fl F Ar modifier Flush the filter parameters specified by .Ar modifier @@ -173,6 +166,8 @@ Flush the queue rules. Flush the filter rules. .It Fl F Ar state Flush the state table (NAT and filter). +.It Fl F Ar Sources +Flush the source tracking table. .It Fl F Ar info Flush the filter information (statistics that are not bound to rules). .It Fl F Ar Tables @@ -182,8 +177,22 @@ Flush the passive operating system fingerprints. .It Fl F Ar all Flush all of the above. .El +.It Fl f Ar file +Load the rules contained in +.Ar file . +This +.Ar file +may contain macros, tables, options, and normalization, queueing, +translation, and filtering rules. +With the exception of macros and tables, the statements must appear in that +order. .It Fl g Include output helpful for debugging. +.It Fl h +Help. +.It Fl i Ar interface +Restrict the operation to the given +.Ar interface . .It Fl k Ar host Kill all of the state entries originating from the specified .Ar host . @@ -207,29 +216,32 @@ to .Bd -literal -offset indent # pfctl -k host1 -k host2 .Ed -.It Fl h -Help. -.It Fl n -Do not actually load rules, just parse them. .It Fl N Load only the NAT rules present in the rule file. Other rules and options are ignored. +.It Fl n +Do not actually load rules, just parse them. +.It Fl O +Load only the options present in the rule file. +Other rules and options are ignored. +.It Fl p Ar device +Use the device file +.Ar device +instead of the default +.Pa /dev/pf . .It Fl q Only print errors and warnings. -.It Fl r -Perform reverse DNS lookups on states when displaying them. .It Fl R Load only the filter rules present in the rule file. Other rules and options are ignored. -.It Fl O -Load only the options present in the rule file. -Other rules and options are ignored. +.It Fl r +Perform reverse DNS lookups on states when displaying them. .It Fl s Ar modifier Show the filter parameters specified by .Ar modifier (may be abbreviated): .Pp -.Bl -tag -width xxxxxxxxxxxx -compact +.Bl -tag -width xxxxxxxxxxxxx -compact .It Fl s Ar nat Show the currently loaded NAT rules. .It Fl s Ar queue @@ -261,8 +273,13 @@ is specified as well, the named rulesets currently loaded in the specified anchor are shown instead. .It Fl s Ar state Show the contents of the state table. +.It Fl s Ar Sources +Show the contents of the source tracking table. .It Fl s Ar info Show filter information (statistics and counters). +When used together with +.Fl v , +source tracking statistics are also shown. .It Fl s Ar labels Show per-rule statistics (label, evaluations, packets, bytes) of filter rules with labels, useful for accounting. @@ -274,16 +291,17 @@ Show the current pool memory hard limits. Show the list of tables. .It Fl s Ar osfp Show the list of operating system fingerprints. -Can be used in combination with -.Fl o Ar file -to list the fingerprints in a -.Xr pf.os 5 -file. +.It Fl s Ar Interfaces +Show the list of interfaces and interface drivers available to PF. +When used together with a double +.Fl v , +interface statistics are also shown. +.Fl i +can be used to select an interface or a group of interfaces. .It Fl s Ar all -Show all of the above. +Show all of the above, except for the lists of interfaces and operating +system fingerprints. .El -.It Fl t Ar table -Specify the name of the table. .It Fl T Ar command Op Ar address ... Specify the .Ar command @@ -334,7 +352,7 @@ Comments starting with a "#" are allowed in the text file. With these commands, the .Fl v flag can also be used once or twice, in which case -.Nm pfctl +.Nm will print the detailed result of the operation for each individual address, prefixed by one of the following letters: @@ -359,7 +377,7 @@ The address/network has been cleared (statistics). Each table maintains a set of counters that can be retrieved using the .Fl v flag of -.Nm pfctl . +.Nm . For example, the following commands define a wide open firewall which will keep track of packets going to or coming from the .Ox @@ -367,8 +385,8 @@ ftp server. The following commands configure the firewall and send 10 pings to the ftp server: .Bd -literal -offset indent -# printf \&"table <test> { ftp.openbsd.org }\en \e -\ \ pass out to <test> keep state\en" \&| pfctl -f- +# printf "table <test> { ftp.openbsd.org }\en \e + pass out to <test> keep state\en" | pfctl -f- # ping -qc10 ftp.openbsd.org .Ed .Pp @@ -381,12 +399,12 @@ The time at which the current accounting started is also shown with the line. .Bd -literal -offset indent # pfctl -t test -vTshow -\ \ \ 129.128.5.191 -\ \ \ \ Cleared: \ \ \ \ Thu Feb 13 18:55:18 2003 -\ \ \ \ In/Block: \ \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ] -\ \ \ \ In/Pass: \ \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ] -\ \ \ \ Out/Block: \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ] -\ \ \ \ Out/Pass: \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ] + 129.128.5.191 + Cleared: Thu Feb 13 18:55:18 2003 + In/Block: [ Packets: 0 Bytes: 0 ] + In/Pass: [ Packets: 10 Bytes: 840 ] + Out/Block: [ Packets: 0 Bytes: 0 ] + Out/Pass: [ Packets: 10 Bytes: 840 ] .Ed .Pp Similarly, it is possible to view global information about the tables @@ -401,19 +419,19 @@ packet statistics for the whole table: .Bd -literal -offset indent # pfctl -vvsTables --a-r- test -\ \ \ \ Addresses: \ \ 1 -\ \ \ \ Cleared: \ \ \ \ Thu Feb 13 18:55:18 2003 -\ \ \ \ References: \ [ Anchors: 0 \ \ \ \ \ \ \ Rules: 1 \ \ \ \ \ \ \ ] -\ \ \ \ Evaluations: [ NoMatch: 3496 \ \ \ \ Match: 1 \ \ \ \ \ \ \ ] -\ \ \ \ In/Block: \ \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ] -\ \ \ \ In/Pass: \ \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ] -\ \ \ \ In/XPass: \ \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ] -\ \ \ \ Out/Block: \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ] -\ \ \ \ Out/Pass: \ \ \ [ Packets: 10 \ \ \ \ \ \ Bytes: 840 \ \ \ \ \ ] -\ \ \ \ Out/XPass: \ \ [ Packets: 0 \ \ \ \ \ \ \ Bytes: 0 \ \ \ \ \ \ \ ] + Addresses: 1 + Cleared: Thu Feb 13 18:55:18 2003 + References: [ Anchors: 0 Rules: 1 ] + Evaluations: [ NoMatch: 3496 Match: 1 ] + In/Block: [ Packets: 0 Bytes: 0 ] + In/Pass: [ Packets: 10 Bytes: 840 ] + In/XPass: [ Packets: 0 Bytes: 0 ] + Out/Block: [ Packets: 0 Bytes: 0 ] + Out/Pass: [ Packets: 10 Bytes: 840 ] + Out/XPass: [ Packets: 0 Bytes: 0 ] .Ed .Pp -As we can see here, only one packet - the initial ping request - matched the +As we can see here, only one packet \- the initial ping request \- matched the table; but all packets passing as the result of the state are correctly accounted for. Reloading the table(s) or ruleset will not affect packet accounting in any way. @@ -421,14 +439,14 @@ The two .Ar XPass counters are incremented instead of the .Ar Pass -counters when a \&"stateful\&" packet is passed but doesn't match the table +counters when a "stateful" packet is passed but doesn't match the table anymore. This will happen in our example if someone flushes the table while the ping command is running. .Pp When used with a single .Fl v , -.Nm pfctl +.Nm will only display the first line containing the table flags and name. The flags are defined as follows: .Pp @@ -459,6 +477,8 @@ For tables which are referenced (used) by rules. This flag is set when a table in the main ruleset is hidden by one or more tables of the same name in sub-rulesets (anchors). .El +.It Fl t Ar table +Specify the name of the table. .It Fl v Produce more verbose output. A second use of diff --git a/contrib/pf/pfctl/pfctl_osfp.c b/contrib/pf/pfctl/pfctl_osfp.c index 9585314..6d1fb99 100644 --- a/contrib/pf/pfctl/pfctl_osfp.c +++ b/contrib/pf/pfctl/pfctl_osfp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_osfp.c,v 1.4 2003/08/27 17:42:00 frantzen Exp $ */ +/* $OpenBSD: pfctl_osfp.c,v 1.8 2004/02/27 10:42:00 henning Exp $ */ /* * Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org> @@ -31,6 +31,7 @@ #include <string.h> #include "pfctl_parser.h" +#include "pfctl.h" #ifndef MIN # define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -308,11 +309,17 @@ pfctl_load_fingerprints(int dev, int opts) void pfctl_show_fingerprints(int opts) { - printf("Passive OS Fingerprints:\n"); - printf("\tClass\tVersion\tSubtype(subversion)\n"); - printf("\t-----\t-------\t-------------------\n"); - sort_name_list(opts, &classes); - print_name_list(opts, &classes, "\t"); + if (LIST_FIRST(&classes) != NULL) { + if (opts & PF_OPT_SHOWALL) { + pfctl_print_title("OS FINGERPRINTS:"); + printf("%u fingerprints loaded\n", fingerprint_count); + } else { + printf("Class\tVersion\tSubtype(subversion)\n"); + printf("-----\t-------\t-------------------\n"); + sort_name_list(opts, &classes); + print_name_list(opts, &classes, ""); + } + } } /* Lookup a fingerprint */ @@ -825,7 +832,7 @@ get_int(char **line, size_t *len, int *var, int *mod, } for (; i < fieldlen; i++) { - if (field[i] < '0' || field[i] > '9') { + if (field[i] < '0' || field[i] > '9') { fprintf(stderr, "%s:%d non-digit character in %s\n", filename, lineno, name); return (1); diff --git a/contrib/pf/pfctl/pfctl_radix.c b/contrib/pf/pfctl/pfctl_radix.c index 788522c..04fb487 100644 --- a/contrib/pf/pfctl/pfctl_radix.c +++ b/contrib/pf/pfctl/pfctl_radix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_radix.c,v 1.21 2003/09/24 09:12:35 cedric Exp $ */ +/* $OpenBSD: pfctl_radix.c,v 1.24 2004/02/10 18:29:30 henning Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -259,7 +259,8 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, { struct pfioc_table io; - if (tbl == NULL || size == NULL || *size < 0 || (*size && addr == NULL)) { + if (tbl == NULL || size == NULL || *size < 0 || + (*size && addr == NULL)) { errno = EINVAL; return (-1); } @@ -281,7 +282,8 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, { struct pfioc_table io; - if (tbl == NULL || size == NULL || *size < 0 || (*size && addr == NULL)) { + if (tbl == NULL || size == NULL || *size < 0 || + (*size && addr == NULL)) { errno = EINVAL; return (-1); } @@ -454,11 +456,40 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, return (0); } +/* interface management code */ + +int +pfi_get_ifaces(const char *filter, struct pfi_if *buf, int *size, int flags) +{ + struct pfioc_iface io; + + if (size == NULL || *size < 0 || (*size && buf == NULL)) { + errno = EINVAL; + return (-1); + } + bzero(&io, sizeof io); + io.pfiio_flags = flags; + if (filter != NULL) + if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >= + sizeof(io.pfiio_name)) { + errno = EINVAL; + return (-1); + } + io.pfiio_buffer = buf; + io.pfiio_esize = sizeof(*buf); + io.pfiio_size = *size; + if (ioctl(dev, DIOCIGETIFACES, &io)) + return (-1); + *size = io.pfiio_size; + return (0); +} + /* buffer management code */ size_t buf_esize[PFRB_MAX] = { 0, sizeof(struct pfr_table), sizeof(struct pfr_tstats), sizeof(struct pfr_addr), sizeof(struct pfr_astats), + sizeof(struct pfi_if), sizeof(struct pfioc_trans_e) }; /* diff --git a/contrib/pf/pflogd/pflogd.8 b/contrib/pf/pflogd/pflogd.8 index ab63259..ac8fe78 100644 --- a/contrib/pf/pflogd/pflogd.8 +++ b/contrib/pf/pflogd/pflogd.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pflogd.8,v 1.22 2003/06/03 13:16:08 jmc Exp $ +.\" $OpenBSD: pflogd.8,v 1.24 2004/01/16 10:45:49 jmc Exp $ .\" .\" Copyright (c) 2001 Can Erkin Acar. All rights reserved. .\" @@ -32,7 +32,7 @@ .Nd packet filter logging daemon .Sh SYNOPSIS .Nm pflogd -.Op Fl D +.Op Fl Dx .Op Fl d Ar delay .Op Fl f Ar filename .Op Fl s Ar snaplen @@ -57,11 +57,11 @@ hopefully offline in case there are bugs in the packet parsing code of .Pp .Nm closes and then re-opens the log file when it receives -.Va SIGHUP , +.Dv SIGHUP , permitting .Xr newsyslog 8 to rotate logfiles automatically. -.Va SIGALRM +.Dv SIGALRM causes .Nm to flush the current logfile buffers to the disk, thus making the most @@ -71,22 +71,32 @@ The buffers are also flushed every seconds. .Pp If the log file contains data after a restart or a -.Va SIGHUP , +.Dv SIGHUP , new logs are appended to the existing file. If the existing log file was created with a different snaplen, .Nm temporarily uses the old snaplen to keep the log file consistent. .Pp +.Nm +tries to preserve the integrity of the log file against I/O errors. +Furthermore, integrity of an existing log file is verified before +appending. +If there is an invalid log file or an I/O error, logging is suspended until a +.Dv SIGHUP +or a +.Dv SIGALRM +is received. +.Pp The options are as follows: .Bl -tag -width Ds -.It Fl d Ar delay -Time in seconds to delay between automatic flushes of the file. -This may be specified with a value between 5 and 3600 seconds. -If not specified, the default is 60 seconds. .It Fl D Debugging mode. .Nm does not disassociate from the controlling terminal. +.It Fl d Ar delay +Time in seconds to delay between automatic flushes of the file. +This may be specified with a value between 5 and 3600 seconds. +If not specified, the default is 60 seconds. .It Fl f Ar filename Log output filename. Default is @@ -98,6 +108,8 @@ bytes of data from each packet rather than the default of 96. The default of 96 is adequate for IP, ICMP, TCP, and UDP headers but may truncate protocol information for other protocols. Other file parsers may desire a higher snaplen. +.It Fl x +Check the integrity of an existing log file, and return. .It Ar expression Selects which packets will be dumped, using the regular language of .Xr tcpdump 8 . @@ -106,13 +118,13 @@ Selects which packets will be dumped, using the regular language of .Bl -tag -width /var/run/pflogd.pid -compact .It Pa /var/run/pflogd.pid Process ID of the currently running -.Nm pflogd . +.Nm . .It Pa /var/log/pflog Default log file. .El .Sh EXAMPLES Log specific tcp packets to a different log file with a large snaplen -(useful with a log-all rule to dump complete sessions) +(useful with a log-all rule to dump complete sessions): .Bd -literal -offset indent # pflogd -s 1600 -f suspicious.log port 80 and host evilhost .Ed @@ -123,7 +135,8 @@ Display binary logs: .Ed .Pp Display the logs in real time (this does not interfere with the -operation of pflogd): +operation of +.Nm ) : .Bd -literal -offset indent # tcpdump -n -e -ttt -i pflog0 .Ed @@ -133,7 +146,7 @@ structure defined in .Aq Ar net/if_pflog.h . Tcpdump can restrict the output to packets logged on a specified interface, a rule number, a reason, -a direction, an ip family or an action. +a direction, an IP family or an action. .Pp .Bl -tag -width "reason match " -compact .It ip @@ -141,9 +154,9 @@ Address family equals IPv4. .It ip6 Address family equals IPv6. .It ifname kue0 -Interface name equals "kue0" +Interface name equals "kue0". .It on kue0 -Interface name equals "kue0" +Interface name equals "kue0". .It rulenum 10 Rule number equals 10. .It reason match diff --git a/contrib/pf/pflogd/pflogd.h b/contrib/pf/pflogd/pflogd.h new file mode 100644 index 0000000..3baecb6 --- /dev/null +++ b/contrib/pf/pflogd/pflogd.h @@ -0,0 +1,47 @@ +/* $OpenBSD: pflogd.h,v 1.2 2004/01/15 20:15:14 canacar Exp $ */ + +/* + * Copyright (c) 2003 Can Erkin Acar + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/limits.h> +#include <pcap.h> + +#define DEF_SNAPLEN 116 /* default plus allow for larger header of pflog */ +#define PCAP_TO_MS 500 /* pcap read timeout (ms) */ +#define PCAP_NUM_PKTS 1000 /* max number of packets to process at each loop */ +#define PCAP_OPT_FIL 1 /* filter optimization */ +#define FLUSH_DELAY 60 /* flush delay */ + +#define PFLOGD_LOG_FILE "/var/log/pflog" +#define PFLOGD_DEFAULT_IF "pflog0" + +#define PFLOGD_MAXSNAPLEN INT_MAX +#define PFLOGD_BUFSIZE 65536 /* buffer size for incoming packets */ + +void logmsg(int priority, const char *message, ...); + +/* Privilege separation */ +int priv_init(void); +int priv_set_snaplen(int snaplen); +int priv_open_log(void); +pcap_t *pcap_open_live_fd(int fd, int snaplen, char *ebuf); + +void set_pcap_filter(void); +/* File descriptor send/recv */ +void send_fd(int, int); +int receive_fd(int); + +extern int Debug; diff --git a/contrib/pf/pflogd/privsep.c b/contrib/pf/pflogd/privsep.c new file mode 100644 index 0000000..50807ad --- /dev/null +++ b/contrib/pf/pflogd/privsep.c @@ -0,0 +1,305 @@ +/* $OpenBSD: privsep.c,v 1.8 2004/03/14 19:17:05 otto Exp $ */ + +/* + * Copyright (c) 2003 Can Erkin Acar + * Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#include <net/if.h> +#include <net/bpf.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <pcap.h> +#include <pcap-int.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include "pflogd.h" + +enum cmd_types { + PRIV_SET_SNAPLEN, /* set the snaplength */ + PRIV_OPEN_LOG /* open logfile for appending */ +}; + +static int priv_fd = -1; +static volatile pid_t child_pid = -1; + +volatile sig_atomic_t gotsig_chld = 0; + +static void sig_pass_to_chld(int); +static void sig_chld(int); +static int may_read(int, void *, size_t); +static void must_read(int, void *, size_t); +static void must_write(int, void *, size_t); +static int set_snaplen(int snap); + +/* bpf filter expression common to parent and child */ +extern char *filter; +extern char *errbuf; +extern char *filename; +extern pcap_t *hpcap; + +/* based on syslogd privsep */ +int +priv_init(void) +{ + int i, fd, socks[2], cmd; + int snaplen, ret; + struct passwd *pw; + + for (i = 1; i < _NSIG; i++) + signal(i, SIG_DFL); + + /* Create sockets */ + if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1) + err(1, "socketpair() failed"); + + pw = getpwnam("_pflogd"); + if (pw == NULL) + errx(1, "unknown user _pflogd"); + endpwent(); + + child_pid = fork(); + if (child_pid < 0) + err(1, "fork() failed"); + + if (!child_pid) { + gid_t gidset[1]; + + /* Child - drop privileges and return */ + if (chroot(pw->pw_dir) != 0) + err(1, "unable to chroot"); + if (chdir("/") != 0) + err(1, "unable to chdir"); + + gidset[0] = pw->pw_gid; + if (setgroups(1, gidset) == -1) + err(1, "setgroups() failed"); + if (setegid(pw->pw_gid) == -1) + err(1, "setegid() failed"); + if (setgid(pw->pw_gid) == -1) + err(1, "setgid() failed"); + if (seteuid(pw->pw_uid) == -1) + err(1, "seteuid() failed"); + if (setuid(pw->pw_uid) == -1) + err(1, "setuid() failed"); + close(socks[0]); + priv_fd = socks[1]; + return 0; + } + + /* Father */ + /* Pass ALRM/TERM/HUP through to child, and accept CHLD */ + signal(SIGALRM, sig_pass_to_chld); + signal(SIGTERM, sig_pass_to_chld); + signal(SIGHUP, sig_pass_to_chld); + signal(SIGCHLD, sig_chld); + + setproctitle("[priv]"); + close(socks[1]); + + while (!gotsig_chld) { + if (may_read(socks[0], &cmd, sizeof(int))) + break; + switch (cmd) { + case PRIV_SET_SNAPLEN: + logmsg(LOG_DEBUG, + "[priv]: msg PRIV_SET_SNAPLENGTH received"); + must_read(socks[0], &snaplen, sizeof(int)); + + ret = set_snaplen(snaplen); + if (ret) { + logmsg(LOG_NOTICE, + "[priv]: set_snaplen failed for snaplen %d", + snaplen); + } + + must_write(socks[0], &ret, sizeof(int)); + break; + + case PRIV_OPEN_LOG: + logmsg(LOG_DEBUG, + "[priv]: msg PRIV_OPEN_LOG received"); + /* create or append logs but do not follow symlinks */ + fd = open(filename, + O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW, + 0600); + if (fd < 0) + logmsg(LOG_NOTICE, + "[priv]: failed to open %s: %s", + filename, strerror(errno)); + send_fd(socks[0], fd); + close(fd); + break; + + default: + logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); + _exit(1); + /* NOTREACHED */ + } + } + + _exit(1); +} + +/* this is called from parent */ +static int +set_snaplen(int snap) +{ + if (hpcap == NULL) + return (1); + + hpcap->snapshot = snap; + set_pcap_filter(); + + return 0; +} + + +/* + * send the snaplength to privileged process + */ +int +priv_set_snaplen(int snaplen) +{ + int cmd, ret; + + if (priv_fd < 0) + errx(1, "%s: called from privileged portion", __func__); + + cmd = PRIV_SET_SNAPLEN; + + must_write(priv_fd, &cmd, sizeof(int)); + must_write(priv_fd, &snaplen, sizeof(int)); + + must_read(priv_fd, &ret, sizeof(int)); + + /* also set hpcap->snapshot in child */ + if (ret == 0) + hpcap->snapshot = snaplen; + + return (ret); +} + +/* Open log-file */ +int +priv_open_log(void) +{ + int cmd, fd; + + if (priv_fd < 0) + errx(1, "%s: called from privileged portion\n", __func__); + + cmd = PRIV_OPEN_LOG; + must_write(priv_fd, &cmd, sizeof(int)); + fd = receive_fd(priv_fd); + + return (fd); +} + +/* If priv parent gets a TERM or HUP, pass it through to child instead */ +static void +sig_pass_to_chld(int sig) +{ + int oerrno = errno; + + if (child_pid != -1) + kill(child_pid, sig); + errno = oerrno; +} + +/* if parent gets a SIGCHLD, it will exit */ +static void +sig_chld(int sig) +{ + gotsig_chld = 1; +} + +/* Read all data or return 1 for error. */ +static int +may_read(int fd, void *buf, size_t n) +{ + char *s = buf; + ssize_t res, pos = 0; + + while (n > pos) { + res = read(fd, s + pos, n - pos); + switch (res) { + case -1: + if (errno == EINTR || errno == EAGAIN) + continue; + case 0: + return (1); + default: + pos += res; + } + } + return (0); +} + +/* Read data with the assertion that it all must come through, or + * else abort the process. Based on atomicio() from openssh. */ +static void +must_read(int fd, void *buf, size_t n) +{ + char *s = buf; + ssize_t res, pos = 0; + + while (n > pos) { + res = read(fd, s + pos, n - pos); + switch (res) { + case -1: + if (errno == EINTR || errno == EAGAIN) + continue; + case 0: + _exit(0); + default: + pos += res; + } + } +} + +/* Write data with the assertion that it all has to be written, or + * else abort the process. Based on atomicio() from openssh. */ +static void +must_write(int fd, void *buf, size_t n) +{ + char *s = buf; + ssize_t res, pos = 0; + + while (n > pos) { + res = write(fd, s + pos, n - pos); + switch (res) { + case -1: + if (errno == EINTR || errno == EAGAIN) + continue; + case 0: + _exit(0); + default: + pos += res; + } + } +} diff --git a/contrib/pf/pflogd/privsep_fdpass.c b/contrib/pf/pflogd/privsep_fdpass.c new file mode 100644 index 0000000..166b693 --- /dev/null +++ b/contrib/pf/pflogd/privsep_fdpass.c @@ -0,0 +1,120 @@ +/* $OpenBSD: privsep_fdpass.c,v 1.1 2003/10/22 18:51:55 canacar Exp $ */ + +/* + * Copyright 2001 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Copyright (c) 2002 Matthieu Herrb + * All rights reserved. + * + * 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. + * + * 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 HOLDERS 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. + */ +#include <sys/param.h> +#include <sys/uio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "pflogd.h" + +void +send_fd(int sock, int fd) +{ + struct msghdr msg; + char tmp[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; + struct iovec vec; + int result = 0; + ssize_t n; + + memset(&msg, 0, sizeof(msg)); + + if (fd >= 0) { + msg.msg_control = (caddr_t)tmp; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; + } else { + result = errno; + } + + vec.iov_base = &result; + vec.iov_len = sizeof(int); + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + + if ((n = sendmsg(sock, &msg, 0)) == -1) + warn("%s: sendmsg(%d)", __func__, sock); + if (n != sizeof(int)) + warnx("%s: sendmsg: expected sent 1 got %ld", + __func__, (long)n); +} + +int +receive_fd(int sock) +{ + struct msghdr msg; + char tmp[CMSG_SPACE(sizeof(int))]; + struct cmsghdr *cmsg; + struct iovec vec; + ssize_t n; + int result; + int fd; + + memset(&msg, 0, sizeof(msg)); + vec.iov_base = &result; + vec.iov_len = sizeof(int); + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_control = tmp; + msg.msg_controllen = sizeof(tmp); + + if ((n = recvmsg(sock, &msg, 0)) == -1) + warn("%s: recvmsg", __func__); + if (n != sizeof(int)) + warnx("%s: recvmsg: expected received 1 got %ld", + __func__, (long)n); + if (result == 0) { + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_type != SCM_RIGHTS) + warnx("%s: expected type %d got %d", __func__, + SCM_RIGHTS, cmsg->cmsg_type); + fd = (*(int *)CMSG_DATA(cmsg)); + return fd; + } else { + errno = result; + return -1; + } +} |