Differences

This shows you the differences between two versions of the page.

Link to this comparison view

openbsd_pf_users_guide_en [2019/08/08 15:24]
127.0.0.1 external edit
openbsd_pf_users_guide_en [2019/08/10 14:40] (current)
Douglas Quintiliano dos Santos
Line 64: Line 64:
  
 When [[http://​man.openbsd.org/​pfctl|pfctl(8)]] encounters a list during loading of the ruleset, it creates multiple rules, one for each item in the list. For example: When [[http://​man.openbsd.org/​pfctl|pfctl(8)]] encounters a list during loading of the ruleset, it creates multiple rules, one for each item in the list. For example:
-<​sxh ​pf>+<​sxh ​bash>
 block out on fxp0 from { 192.168.0.1,​ 10.5.32.6 } to any block out on fxp0 from { 192.168.0.1,​ 10.5.32.6 } to any
 </​sxh>​ </​sxh>​
  
 gets expanded to: gets expanded to:
-<​sxh ​pf>+<​sxh ​bash>
 block out on fxp0 from 192.168.0.1 to any block out on fxp0 from 192.168.0.1 to any
 block out on fxp0 from 10.5.32.6 to any block out on fxp0 from 10.5.32.6 to any
Line 75: Line 75:
  
 Multiple lists can be specified within a rule: Multiple lists can be specified within a rule:
-<​sxh ​pf>+<​sxh ​bash>
 match in on fxp0 proto tcp to port { 22 80 } rdr-to 192.168.0.6 match in on fxp0 proto tcp to port { 22 80 } rdr-to 192.168.0.6
 block out on fxp0 proto { tcp udp } from { 192.168.0.1,​ 10.5.32.6 } \ block out on fxp0 proto { tcp udp } from { 192.168.0.1,​ 10.5.32.6 } \
Line 85: Line 85:
  
 Lists can also contain nested lists: Lists can also contain nested lists:
-<​sxh ​pf>+<​sxh ​bash>
 trusted = "{ 192.168.1.2 192.168.5.36 }" trusted = "{ 192.168.1.2 192.168.5.36 }"
 pass in inet proto tcp from { 10.10.0.0/​24 $trusted } to port 22 pass in inet proto tcp from { 10.10.0.0/​24 $trusted } to port 22
Line 91: Line 91:
  
 Beware of constructs like the following, dubbed "​negated lists,"​ which are a common mistake: Beware of constructs like the following, dubbed "​negated lists,"​ which are a common mistake:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on fxp0 from { 10.0.0.0/8, !10.1.2.3 } pass in on fxp0 from { 10.0.0.0/8, !10.1.2.3 }
 </​sxh>​ </​sxh>​
  
 While the intended meaning is usually to match "any address within 10.0.0.0/8, except for 10.1.2.3,"​ the rule expands to: While the intended meaning is usually to match "any address within 10.0.0.0/8, except for 10.1.2.3,"​ the rule expands to:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on fxp0 from 10.0.0.0/8 pass in on fxp0 from 10.0.0.0/8
 pass in on fxp0 from !10.1.2.3 pass in on fxp0 from !10.1.2.3
Line 107: Line 107:
 Macros are user-defined variables that can hold IP addresses, port numbers, interface names, etc. Macros can reduce the complexity of a PF ruleset and also make maintaining a ruleset much easier. Macros are user-defined variables that can hold IP addresses, port numbers, interface names, etc. Macros can reduce the complexity of a PF ruleset and also make maintaining a ruleset much easier.
 Macro names must start with a letter and may contain letters, digits and underscores. Macro names cannot be reserved words such as pass, out or queue. Macro names must start with a letter and may contain letters, digits and underscores. Macro names cannot be reserved words such as pass, out or queue.
-<​sxh ​pf>+<​sxh ​bash>
 ext_if = "​fxp0"​ ext_if = "​fxp0"​
  
Line 115: Line 115:
 This creates a macro named ext_if. When a macro is referred to after it's been created, its name is preceded with a $ character. This creates a macro named ext_if. When a macro is referred to after it's been created, its name is preceded with a $ character.
 Macros can also expand to lists, such as: Macros can also expand to lists, such as:
-<​sxh ​pf>+<​sxh ​bash>
 friends = "{ 192.168.1.1,​ 10.0.2.5, 192.168.43.53 }" friends = "{ 192.168.1.1,​ 10.0.2.5, 192.168.43.53 }"
 </​sxh>​ </​sxh>​
  
 Macros can be defined recursively. Since macros are not expanded within quotes the following syntax must be used: Macros can be defined recursively. Since macros are not expanded within quotes the following syntax must be used:
-<​sxh ​pf>+<​sxh ​bash>
 host1      = "​192.168.1.1"​ host1      = "​192.168.1.1"​
 host2      = "​192.168.1.2"​ host2      = "​192.168.1.2"​
Line 150: Line 150:
  
 Example: Example:
-<​sxh ​pf>+<​sxh ​bash>
 table <​goodguys>​ { 192.0.2.0/​24 } table <​goodguys>​ { 192.0.2.0/​24 }
 table <​rfc1918> ​ const { 192.168.0.0/​16,​ 172.16.0.0/​12,​ 10.0.0.0/8 } table <​rfc1918> ​ const { 192.168.0.0/​16,​ 172.16.0.0/​12,​ 10.0.0.0/8 }
Line 159: Line 159:
  
 Addresses can also be specified using the negation (or "​not"​) modifier, such as: Addresses can also be specified using the negation (or "​not"​) modifier, such as:
-<​sxh ​pf>+<​sxh ​bash>
 table <​goodguys>​ { 192.0.2.0/​24,​ !192.0.2.5 } table <​goodguys>​ { 192.0.2.0/​24,​ !192.0.2.5 }
 </​sxh>​ </​sxh>​
Line 166: Line 166:
  
 Tables can also be populated from text files containing a list of IP addresses and networks: Tables can also be populated from text files containing a list of IP addresses and networks:
-<​sxh ​pf>+<​sxh ​bash>
 table <​spammers>​ persist file "/​etc/​spammers"​ table <​spammers>​ persist file "/​etc/​spammers"​
 block in on fxp0 from <​spammers>​ to any block in on fxp0 from <​spammers>​ to any
Line 201: Line 201:
  
 An address lookup against a table will return the most narrowly matching entry. This allows for the creation of tables such as: An address lookup against a table will return the most narrowly matching entry. This allows for the creation of tables such as:
-<​sxh ​pf>+<​sxh ​bash>
 table <​goodguys>​ { 172.16.0.0/​16,​ !172.16.1.0/​24,​ 172.16.1.100 } table <​goodguys>​ { 172.16.0.0/​16,​ !172.16.1.0/​24,​ 172.16.1.100 }
 block in on dc0 block in on dc0
Line 303: Line 303:
  
 To create a default deny filter policy, the first filter rule should be: To create a default deny filter policy, the first filter rule should be:
-<​sxh ​pf>+<​sxh ​bash>
 block all block all
 </​sxh>​ </​sxh>​
Line 314: Line 314:
  
 Some examples: Some examples:
-<​sxh ​pf>+<​sxh ​bash>
 # Pass traffic in on dc0 from the local network, 192.168.0.0/​24,​ to the OpenBSD # Pass traffic in on dc0 from the local network, 192.168.0.0/​24,​ to the OpenBSD
 # machine'​s IP address 192.168.0.1. Also, pass the return traffic out on dc0. # machine'​s IP address 192.168.0.1. Also, pass the return traffic out on dc0.
Line 331: Line 331:
  
 Wrong: Wrong:
-<​sxh ​pf>+<​sxh ​bash>
 block in on fxp0 proto tcp to port ssh block in on fxp0 proto tcp to port ssh
 pass  in all pass  in all
Line 339: Line 339:
  
 Better: Better:
-<​sxh ​pf>+<​sxh ​bash>
 block in quick on fxp0 proto tcp to port ssh block in quick on fxp0 proto tcp to port ssh
 pass  in all pass  in all
Line 355: Line 355:
  
 All **pass** rules automatically create a state entry when a packet matches the rule. This can be explicitly disabled by using the **no state** option. All **pass** rules automatically create a state entry when a packet matches the rule. This can be explicitly disabled by using the **no state** option.
-<​sxh ​pf>+<​sxh ​bash>
 pass out on fxp0 proto tcp from any to any pass out on fxp0 proto tcp from any to any
 </​sxh>​ </​sxh>​
Line 364: Line 364:
  
 Keep state on outgoing TCP, UDP and ICMP packets and modulate TCP ISNs: Keep state on outgoing TCP, UDP and ICMP packets and modulate TCP ISNs:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state
 </​sxh>​ </​sxh>​
Line 371: Line 371:
  
 The scope of a state entry is controlled globally by the state-policy runtime option, and on a per-rule basis by the **if-bound** and **floating** state option keywords. These per-rule keywords have the same meaning as when used with the **state-policy** option. For example: The scope of a state entry is controlled globally by the state-policy runtime option, and on a per-rule basis by the **if-bound** and **floating** state option keywords. These per-rule keywords have the same meaning as when used with the **state-policy** option. For example:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state (if-bound) pass out on fxp0 proto { tcp, udp, icmp } from any to any modulate state (if-bound)
 </​sxh>​ </​sxh>​
Line 401: Line 401:
  
 An example rule: An example rule:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on $ext_if proto tcp to $web_server port www keep state   \ pass in on $ext_if proto tcp to $web_server port www keep state   \
                   (max 200, source-track rule, max-src-nodes 100, \                   (max 200, source-track rule, max-src-nodes 100, \
Line 430: Line 430:
  
 An example: An example:
-<​sxh ​pf>+<​sxh ​bash>
 table <​abusive_hosts>​ persist table <​abusive_hosts>​ persist
 block in quick from <​abusive_hosts>​ block in quick from <​abusive_hosts>​
Line 459: Line 459:
  
 To have PF inspect the TCP flags during evaluation of a rule, the flags keyword is used with the following syntax: To have PF inspect the TCP flags during evaluation of a rule, the flags keyword is used with the following syntax:
-<​sxh ​pf>+<​sxh ​bash>
 flags check/mask flags check/mask
 flags any flags any
Line 465: Line 465:
  
 The mask part tells PF to only inspect the specified flags and the check part specifies which flag(s) must be "​on"​ in the header for a match to occur. Using the any keyword allows any combination of flags to be set in the header. The mask part tells PF to only inspect the specified flags and the check part specifies which flag(s) must be "​on"​ in the header for a match to occur. Using the any keyword allows any combination of flags to be set in the header.
-<​sxh ​pf>+<​sxh ​bash>
 pass in on fxp0 proto tcp from any to any port ssh flags S/SA pass in on fxp0 proto tcp from any to any port ssh flags S/SA
 pass in on fxp0 proto tcp from any to any port ssh pass in on fxp0 proto tcp from any to any port ssh
Line 475: Line 475:
  
 One should be careful with using flags -- understand what you are doing and why, and be careful with the advice people give as a lot of it is bad. Some people have suggested creating state "only if the SYN flag is set and no others."​ Such a rule would end with: One should be careful with using flags -- understand what you are doing and why, and be careful with the advice people give as a lot of it is bad. Some people have suggested creating state "only if the SYN flag is set and no others."​ Such a rule would end with:
-<​sxh ​pf>+<​sxh ​bash>
 [...] flags S/​FSRPAUEW ​ bad idea!! [...] flags S/​FSRPAUEW ​ bad idea!!
 </​sxh>​ </​sxh>​
  
 The theory is to create state only on the start of the TCP session, and the session should start with a SYN flag, and no others. The problem is some sites are starting to use the ECN flag and any site using ECN that tries to connect to you would be rejected by such a rule. A much better guideline is to not specify any flags at all and let PF apply the default flags to your rules. If you truly need to specify flags yourself, then this combination should be safe: The theory is to create state only on the start of the TCP session, and the session should start with a SYN flag, and no others. The problem is some sites are starting to use the ECN flag and any site using ECN that tries to connect to you would be rejected by such a rule. A much better guideline is to not specify any flags at all and let PF apply the default flags to your rules. If you truly need to specify flags yourself, then this combination should be safe:
-<​sxh ​pf>+<​sxh ​bash>
 [...] flags S/SAFR [...] flags S/SAFR
 </​sxh>​ </​sxh>​
Line 491: Line 491:
  
 The TCP SYN proxy is enabled using the synproxy state keywords in filter rules. For example: The TCP SYN proxy is enabled using the synproxy state keywords in filter rules. For example:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on $ext_if proto tcp to $web_server port www synproxy state pass in on $ext_if proto tcp to $web_server port www synproxy state
 </​sxh>​ </​sxh>​
Line 506: Line 506:
  
 PF offers some protection against address spoofing through the antispoof keyword: PF offers some protection against address spoofing through the antispoof keyword:
-<​sxh ​pf>+<​sxh ​bash>
 antispoof [log] [quick] for interface [af] antispoof [log] [quick] for interface [af]
 </​sxh>​ </​sxh>​
Line 520: Line 520:
  
 Example: Example:
-<​sxh ​pf>+<​sxh ​bash>
 antispoof for fxp0 inet antispoof for fxp0 inet
 </​sxh>​ </​sxh>​
  
 When a ruleset is loaded, any occurrences of the antispoof keyword are expanded into two filter rules. Assuming that interface fxp0 has IP address 10.0.0.1 and a subnet mask of 255.255.255.0 (i.e., a /24), the above antispoof rule would expand to: When a ruleset is loaded, any occurrences of the antispoof keyword are expanded into two filter rules. Assuming that interface fxp0 has IP address 10.0.0.1 and a subnet mask of 255.255.255.0 (i.e., a /24), the above antispoof rule would expand to:
-<​sxh ​pf>+<​sxh ​bash>
 block in on ! fxp0 inet from 10.0.0.0/24 to any block in on ! fxp0 inet from 10.0.0.0/24 to any
 block in inet from 10.0.0.1 to any block in inet from 10.0.0.1 to any
Line 537: Line 537:
 **NOTE:** The filter rules that the **antispoof** rule expands to will also block packets sent over the loopback interface to local addresses. It's best practice to skip filtering on loopback interfaces anyways, but this becomes a necessity when using antispoof rules: **NOTE:** The filter rules that the **antispoof** rule expands to will also block packets sent over the loopback interface to local addresses. It's best practice to skip filtering on loopback interfaces anyways, but this becomes a necessity when using antispoof rules:
  
-<​sxh ​pf>+<​sxh ​bash>
 set skip on lo0 set skip on lo0
 antispoof for fxp0 inet antispoof for fxp0 inet
Line 543: Line 543:
  
 Usage of antispoof should be restricted to interfaces that have been assigned an IP address. Using **antispoof** on an interface without an IP address will result in filter rules such as: Usage of antispoof should be restricted to interfaces that have been assigned an IP address. Using **antispoof** on an interface without an IP address will result in filter rules such as:
-<​sxh ​pf>+<​sxh ​bash>
 block drop in on ! fxp0 inet all block drop in on ! fxp0 inet all
 block drop in net all block drop in net all
Line 555: Line 555:
  
 The uRPF check can be performed on packets by using the urpf-failed keyword in filter rules: The uRPF check can be performed on packets by using the urpf-failed keyword in filter rules:
-<​sxh ​pf>+<​sxh ​bash>
 block in quick from urpf-failed label uRPF block in quick from urpf-failed label uRPF
 </​sxh>​ </​sxh>​
Line 568: Line 568:
  
 PF determines the remote operating system by comparing characteristics of a TCP SYN packet against the fingerprints file, which by default is [[http://​man.openbsd.org/​pf.os|pf.os(5)]]. Once PF is enabled, the current fingerprint list can be viewed with this command: PF determines the remote operating system by comparing characteristics of a TCP SYN packet against the fingerprints file, which by default is [[http://​man.openbsd.org/​pf.os|pf.os(5)]]. Once PF is enabled, the current fingerprint list can be viewed with this command:
-<​sxh ​pf>+<​sxh ​bash>
 pfctl -s osfp pfctl -s osfp
 </​sxh>​ </​sxh>​
  
 Within a filter rule, a fingerprint may be specified by OS class, version, or subtype/​patch level. Each of these items is listed in the output of the pfctl command shown above. To specify a fingerprint in a filter rule, the os keyword is used: Within a filter rule, a fingerprint may be specified by OS class, version, or subtype/​patch level. Each of these items is listed in the output of the pfctl command shown above. To specify a fingerprint in a filter rule, the os keyword is used:
-<​sxh ​pf>+<​sxh ​bash>
 pass  in on $ext_if proto tcp from any os OpenBSD keep state pass  in on $ext_if proto tcp from any os OpenBSD keep state
 block in on $ext_if proto tcp from any os "​Windows 2000" block in on $ext_if proto tcp from any os "​Windows 2000"
Line 591: Line 591:
  
 By default, PF blocks packets with IP options set. This can make the job more difficult for OS fingerprinting utilities like nmap. If you have an application that requires the passing of these packets, such as multicast or IGMP, you can use the allow-opts directive: By default, PF blocks packets with IP options set. This can make the job more difficult for OS fingerprinting utilities like nmap. If you have an application that requires the passing of these packets, such as multicast or IGMP, you can use the allow-opts directive:
-<​sxh ​pf>+<​sxh ​bash>
 pass in quick on fxp0 all allow-opts pass in quick on fxp0 all allow-opts
 </​sxh>​ </​sxh>​
Line 599: Line 599:
 Below is an example of a filtering ruleset. The machine running PF is acting as a firewall between a small, internal network and the Internet. Only the filter rules are shown; queueing, nat, rdr, etc, have been left out of this example. Below is an example of a filtering ruleset. The machine running PF is acting as a firewall between a small, internal network and the Internet. Only the filter rules are shown; queueing, nat, rdr, etc, have been left out of this example.
  
-<​sxh ​pf>+<​sxh ​bash>
 ext_if ​ = "​fxp0"​ ext_if ​ = "​fxp0"​
 int_if ​ = "​dc0"​ int_if ​ = "​dc0"​
Line 775: Line 775:
  
 This would lead to a most basic form of these lines similar to this: This would lead to a most basic form of these lines similar to this:
-<​sxh ​pf>+<​sxh ​bash>
 match out on tl0 from 192.168.1.0/​24 to any nat-to 198.51.100.1 match out on tl0 from 192.168.1.0/​24 to any nat-to 198.51.100.1
 pass on tl0 from 192.168.1.0/​24 to any pass on tl0 from 192.168.1.0/​24 to any
 </​sxh>​ </​sxh>​
 Or you may simply use: Or you may simply use:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on tl0 from 192.168.1.0/​24 to any nat-to 198.51.100.1 pass out on tl0 from 192.168.1.0/​24 to any nat-to 198.51.100.1
 </​sxh>​ </​sxh>​
Line 787: Line 787:
  
 While the above rule is correct, it is not recommended form. Maintenance could be difficult as any change of the external or internal network numbers would require the line be changed. Compare instead with this easier to maintain line (tl0 is external, dc0 internal): While the above rule is correct, it is not recommended form. Maintenance could be difficult as any change of the external or internal network numbers would require the line be changed. Compare instead with this easier to maintain line (tl0 is external, dc0 internal):
-<​sxh ​pf>+<​sxh ​bash>
 pass out on tl0 inet from dc0:network to any nat-to tl0 pass out on tl0 inet from dc0:network to any nat-to tl0
 </​sxh>​ </​sxh>​
Line 794: Line 794:
  
 When specifying an interface name for the translation address as above, the IP address is determined at pf.conf load time, not on the fly. If you are using DHCP to configure your external interface, this can be a problem. If your assigned IP address changes, NAT will continue translating outgoing packets using the old IP address. This will cause outgoing connections to stop functioning. To get around this, you can tell PF to automatically update the translation address by putting parentheses around the interface name: When specifying an interface name for the translation address as above, the IP address is determined at pf.conf load time, not on the fly. If you are using DHCP to configure your external interface, this can be a problem. If your assigned IP address changes, NAT will continue translating outgoing packets using the old IP address. This will cause outgoing connections to stop functioning. To get around this, you can tell PF to automatically update the translation address by putting parentheses around the interface name:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on tl0 inet from dc0:network to any nat-to (tl0) pass out on tl0 inet from dc0:network to any nat-to (tl0)
 </​sxh>​ </​sxh>​
Line 805: Line 805:
  
 Example: Example:
-<​sxh ​pf>+<​sxh ​bash>
 web_serv_int = "​192.168.1.100"​ web_serv_int = "​192.168.1.100"​
 web_serv_ext = "​198.51.100.6"​ web_serv_ext = "​198.51.100.6"​
Line 815: Line 815:
  
 If you need to translate most traffic, but provide exceptions in some cases, make sure that the exceptions are handled by a filter rule which does not include the nat-to parameter. For example, if the NAT example above was modified to look like this: If you need to translate most traffic, but provide exceptions in some cases, make sure that the exceptions are handled by a filter rule which does not include the nat-to parameter. For example, if the NAT example above was modified to look like this:
-<​sxh ​pf>+<​sxh ​bash>
 pass  out on tl0 from 192.168.1.0/​24 to any nat-to 198.51.100.79 pass  out on tl0 from 192.168.1.0/​24 to any nat-to 198.51.100.79
 pass  out on tl0 from 192.168.1.208 ​ to any pass  out on tl0 from 192.168.1.208 ​ to any
Line 825: Line 825:
  
 To view the active NAT translations,​ [[http://​man.openbsd.org/​pfctl|pfctl(8)]] is used with the **-s state** option. This option will list all the current NAT sessions: To view the active NAT translations,​ [[http://​man.openbsd.org/​pfctl|pfctl(8)]] is used with the **-s state** option. This option will list all the current NAT sessions:
-<​sxh ​pf>+<​sxh ​bash>
 pfctl -s state pfctl -s state
 fxp0 tcp 192.168.1.35:​2132 (198.51.100.1:​53136) -> 198.51.100.10:​22 TIME_WAIT:​TIME_WAIT fxp0 tcp 192.168.1.35:​2132 (198.51.100.1:​53136) -> 198.51.100.10:​22 TIME_WAIT:​TIME_WAIT
Line 852: Line 852:
  
 Let's look at an example: Let's look at an example:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on tl0 proto tcp from any to any port 80 rdr-to 192.168.1.20 pass in on tl0 proto tcp from any to any port 80 rdr-to 192.168.1.20
 </​sxh>​ </​sxh>​
Line 859: Line 859:
  
 The **from any to any** part of the above **rdr** line can be quite useful. If you know what addresses or subnets are supposed to have access to the web server at port 80, you can restrict them here: The **from any to any** part of the above **rdr** line can be quite useful. If you know what addresses or subnets are supposed to have access to the web server at port 80, you can restrict them here:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on tl0 proto tcp from 203.0.113.0/​24 to any port 80 rdr-to 192.168.1.20 pass in on tl0 proto tcp from 203.0.113.0/​24 to any port 80 rdr-to 192.168.1.20
 </​sxh>​ </​sxh>​
  
 This will redirect only the specified subnet. Note this implies you can redirect different incoming hosts to different machines behind the gateway. This can be quite useful as well. For example, you could have users at remote sites access their own desktop computers using the same port and IP address on the gateway as long as you know the IP address they will be connecting from. This will redirect only the specified subnet. Note this implies you can redirect different incoming hosts to different machines behind the gateway. This can be quite useful as well. For example, you could have users at remote sites access their own desktop computers using the same port and IP address on the gateway as long as you know the IP address they will be connecting from.
-<​sxh ​pf>+<​sxh ​bash>
 pass in on tl0 proto tcp from 203.0.113.14 to any port 80 rdr-to 192.168.1.20 pass in on tl0 proto tcp from 203.0.113.14 to any port 80 rdr-to 192.168.1.20
 pass in on tl0 proto tcp from 198.51.100.89 to any port 80 rdr-to 192.168.1.22 pass in on tl0 proto tcp from 198.51.100.89 to any port 80 rdr-to 192.168.1.22
Line 870: Line 870:
 </​sxh>​ </​sxh>​
 A range of ports can also be redirected within the same rule: A range of ports can also be redirected within the same rule:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on tl0 proto tcp from any to any port 5000:5500 \ pass in on tl0 proto tcp from any to any port 5000:5500 \
    ​rdr-to 192.168.1.20    ​rdr-to 192.168.1.20
Line 890: Line 890:
  
 Often, redirection rules are used to forward incoming connections from the internet to a local server with a private address in the internal network or LAN, as in: Often, redirection rules are used to forward incoming connections from the internet to a local server with a private address in the internal network or LAN, as in:
-<​sxh ​pf>+<​sxh ​bash>
 server = 192.168.1.40 server = 192.168.1.40
 pass in on $ext_if proto tcp from any to $ext_if port 80 rdr-to $server port 80 pass in on $ext_if proto tcp from any to $ext_if port 80 rdr-to $server port 80
Line 916: Line 916:
  
 With an additional NAT rule on the internal interface, the lacking source address translation described above can be achieved. With an additional NAT rule on the internal interface, the lacking source address translation described above can be achieved.
-<​sxh ​pf>+<​sxh ​bash>
 pass in on $int_if proto tcp from $int_net to $ext_if port 80 rdr-to $server pass in on $int_if proto tcp from $int_net to $ext_if port 80 rdr-to $server
 pass out on $int_if proto tcp to $server port 80 received-on $int_if nat-to $int_if pass out on $int_if proto tcp to $server port 80 received-on $int_if nat-to $int_if
Line 934: Line 934:
  
 A common convention in PF rulesets is to define a macro for each network interface. If a network card ever needs to be replaced with one that uses a different driver, the macro can be updated and the filter rules will function as before. Another benefit is when installing the same ruleset on multiple machines. Certain machines may have different network cards in them, and using macros to define the network interfaces allows the rulesets to be installed with minimal editing. Using macros to define information in a ruleset that is subject to change, such as port numbers, IP addresses, and interface names, is recommended practice. A common convention in PF rulesets is to define a macro for each network interface. If a network card ever needs to be replaced with one that uses a different driver, the macro can be updated and the filter rules will function as before. Another benefit is when installing the same ruleset on multiple machines. Certain machines may have different network cards in them, and using macros to define the network interfaces allows the rulesets to be installed with minimal editing. Using macros to define information in a ruleset that is subject to change, such as port numbers, IP addresses, and interface names, is recommended practice.
-<​sxh ​pf>+<​sxh ​bash>
 # define macros for each network interface # define macros for each network interface
 IntIF = "​dc0"​ IntIF = "​dc0"​
Line 942: Line 942:
  
 Another common convention is using macros to define IP addresses and network blocks. This can greatly reduce the maintenance of a ruleset when IP addresses change. Another common convention is using macros to define IP addresses and network blocks. This can greatly reduce the maintenance of a ruleset when IP addresses change.
-<​sxh ​pf>+<​sxh ​bash>
 # define our networks # define our networks
 IntNet = "​192.168.0.0/​24"​ IntNet = "​192.168.0.0/​24"​
Line 950: Line 950:
  
 If the internal network ever expanded or was renumbered into a different IP block, the macro can be updated: If the internal network ever expanded or was renumbered into a different IP block, the macro can be updated:
-<​sxh ​pf>+<​sxh ​bash>
 IntNet = "{ 192.168.0.0/​24,​ 192.168.1.0/​24 }" IntNet = "{ 192.168.0.0/​24,​ 192.168.1.0/​24 }"
 </​sxh>​ </​sxh>​
Line 959: Line 959:
  
 Let's look at a good set of rules to have in your ruleset to handle [[https://​tools.ietf.org/​html/​rfc1918|RFC 1918]] addresses that just shouldn'​t be floating around the Internet, and when they are, are usually trying to cause trouble: Let's look at a good set of rules to have in your ruleset to handle [[https://​tools.ietf.org/​html/​rfc1918|RFC 1918]] addresses that just shouldn'​t be floating around the Internet, and when they are, are usually trying to cause trouble:
-<​sxh ​pf>+<​sxh ​bash>
 block in  quick on tl0 inet from 127.0.0.0/8 to any block in  quick on tl0 inet from 127.0.0.0/8 to any
 block in  quick on tl0 inet from 192.168.0.0/​16 to any block in  quick on tl0 inet from 192.168.0.0/​16 to any
Line 971: Line 971:
  
 Now look at the following simplification:​ Now look at the following simplification:​
-<​sxh ​pf>+<​sxh ​bash>
 block in quick on tl0 inet from { 127.0.0.0/​8,​ 192.168.0.0/​16,​ \ block in quick on tl0 inet from { 127.0.0.0/​8,​ 192.168.0.0/​16,​ \
    ​172.16.0.0/​12,​ 10.0.0.0/8 } to any    ​172.16.0.0/​12,​ 10.0.0.0/8 } to any
Line 979: Line 979:
  
 The ruleset has been reduced from eight lines down to two. Things get even better when macros are used in conjunction with a list: The ruleset has been reduced from eight lines down to two. Things get even better when macros are used in conjunction with a list:
-<​sxh ​pf>+<​sxh ​bash>
 NoRouteIPs = "{ 127.0.0.0/​8,​ 192.168.0.0/​16,​ 172.16.0.0/​12,​ 10.0.0.0/8 }" NoRouteIPs = "{ 127.0.0.0/​8,​ 192.168.0.0/​16,​ 172.16.0.0/​12,​ 10.0.0.0/8 }"
  
Line 988: Line 988:
  
 Note that macros and lists simplify the pf.conf file, but the lines are actually expanded by [[http://​man.openbsd.org/​pfctl|pfctl(8)]] into multiple rules. So, the above example actually expands to the following rules: Note that macros and lists simplify the pf.conf file, but the lines are actually expanded by [[http://​man.openbsd.org/​pfctl|pfctl(8)]] into multiple rules. So, the above example actually expands to the following rules:
-<​sxh ​pf>+<​sxh ​bash>
 block in  quick on tl0 inet from 127.0.0.0/8 to any block in  quick on tl0 inet from 127.0.0.0/8 to any
 block in  quick on tl0 inet from 192.168.0.0/​16 to any block in  quick on tl0 inet from 192.168.0.0/​16 to any
Line 1002: Line 1002:
  
 Macros can be used to define more than just addresses and ports; they can be used anywhere in a PF rules file: Macros can be used to define more than just addresses and ports; they can be used anywhere in a PF rules file:
-<​sxh ​pf>+<​sxh ​bash>
 pre  = "pass in quick on ep0 inet proto tcp from " pre  = "pass in quick on ep0 inet proto tcp from "
 post = "to any port { 80, 6667 }" post = "to any port { 80, 6667 }"
Line 1012: Line 1012:
  
 Expands to: Expands to:
-<​sxh ​pf>+<​sxh ​bash>
 pass in quick on ep0 inet proto tcp from 198.51.100.80 to any port = 80 pass in quick on ep0 inet proto tcp from 198.51.100.80 to any port = 80
 pass in quick on ep0 inet proto tcp from 198.51.100.80 to any port = 6667 pass in quick on ep0 inet proto tcp from 198.51.100.80 to any port = 6667
Line 1028: Line 1028:
  
 To define a "​default deny" policy, two rules are used: To define a "​default deny" policy, two rules are used:
-<​sxh ​pf>+<​sxh ​bash>
 block in  all block in  all
 block out all block out all
Line 1034: Line 1034:
  
 This can now be reduced to: This can now be reduced to:
-<​sxh ​pf>+<​sxh ​bash>
 block block
 </​sxh>​ </​sxh>​
Line 1041: Line 1041:
  
 Similarly, the "​**from any to any**" and "​**all**"​ clauses can be left out of a rule, for example: Similarly, the "​**from any to any**" and "​**all**"​ clauses can be left out of a rule, for example:
-<​sxh ​pf>+<​sxh ​bash>
 block in on rl0 all block in on rl0 all
 pass  in quick log on rl0 proto tcp from any to any port 22 pass  in quick log on rl0 proto tcp from any to any port 22
Line 1047: Line 1047:
  
 can be simplified as: can be simplified as:
-<​sxh ​pf>+<​sxh ​bash>
 block in on rl0 block in on rl0
 pass  in quick log on rl0 proto tcp to port 22 keep state pass  in quick log on rl0 proto tcp to port 22 keep state
Line 1057: Line 1057:
  
 A ruleset used to block packets and reply with a TCP RST or ICMP Unreachable response could look like this: A ruleset used to block packets and reply with a TCP RST or ICMP Unreachable response could look like this:
-<​sxh ​pf>+<​sxh ​bash>
 block in all block in all
 block return-rst ​ in proto tcp all block return-rst ​ in proto tcp all
Line 1067: Line 1067:
  
 This can be simplified as: This can be simplified as:
-<​sxh ​pf>+<​sxh ​bash>
 block return block return
 </​sxh>​ </​sxh>​
Line 1076: Line 1076:
  
 The order in which keywords are specified is flexible in most cases. For example, a rule written as: The order in which keywords are specified is flexible in most cases. For example, a rule written as:
-<​sxh ​pf>+<​sxh ​bash>
 pass in log quick on rl0 proto tcp to port 22 flags S/SA keep state queue ssh label ssh pass in log quick on rl0 proto tcp to port 22 flags S/SA keep state queue ssh label ssh
 </​sxh>​ </​sxh>​
  
 can also be written as: can also be written as:
-<​sxh ​pf>+<​sxh ​bash>
 pass in quick log on rl0 proto tcp to port 22 queue ssh keep state label ssh flags S/SA pass in quick log on rl0 proto tcp to port 22 queue ssh keep state label ssh flags S/SA
 </​sxh>​ </​sxh>​
Line 1090: Line 1090:
  
 Here is an example of a pf.conf working with the drop policy and with wan, dmz and lan interfaces. Here is an example of a pf.conf working with the drop policy and with wan, dmz and lan interfaces.
-<​sxh ​pf>+<​sxh ​bash>
 vim /​etc/​pf.conf vim /​etc/​pf.conf
 #       ​$OpenBSD:​ pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $ #       ​$OpenBSD:​ pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
Line 1245: Line 1245:
  
 Example: Example:
-<​sxh ​pf>+<​sxh ​bash>
 set timeout interval 10 set timeout interval 10
 set timeout frag 30 set timeout frag 30
Line 1270: Line 1270:
  
 For example: For example:
-<​sxh ​pf>+<​sxh ​bash>
 ext_if = "​fxp0"​ ext_if = "​fxp0"​
 block on $ext_if block on $ext_if
Line 1285: Line 1285:
  
 For example: For example:
-<​sxh ​pf>+<​sxh ​bash>
 anchor goodguys anchor goodguys
 load anchor goodguys from "/​etc/​anchor-goodguys-ssh"​ load anchor goodguys from "/​etc/​anchor-goodguys-ssh"​
Line 1291: Line 1291:
  
 To add rules to an anchor using pfctl, the following type of command can be used: To add rules to an anchor using pfctl, the following type of command can be used:
-<​sxh ​pf>+<​sxh ​bash>
 echo "pass in proto tcp from 192.0.2.3 to any port 22" | pfctl -a goodguys -f - echo "pass in proto tcp from 192.0.2.3 to any port 22" | pfctl -a goodguys -f -
 </​sxh>​ </​sxh>​
  
 Rules can also be saved to (and loaded from) a text file. For example, you could append the following two lines to the /​etc/​anchor-goodguys-www file: Rules can also be saved to (and loaded from) a text file. For example, you could append the following two lines to the /​etc/​anchor-goodguys-www file:
-<​sxh ​pf>+<​sxh ​bash>
 pass in proto tcp from 192.0.2.3 to any port 80 pass in proto tcp from 192.0.2.3 to any port 80
 pass in proto tcp from 192.0.2.4 to any port { 80 443 } pass in proto tcp from 192.0.2.4 to any port { 80 443 }
Line 1302: Line 1302:
  
 Then applied with: Then applied with:
-<​sxh ​pf>+<​sxh ​bash>
 pfctl -a goodguys -f /​etc/​anchor-goodguys-www pfctl -a goodguys -f /​etc/​anchor-goodguys-www
 </​sxh>​ </​sxh>​
  
 To load rules directly from the main ruleset, enclose the anchor rules in a brace-delimited block: To load rules directly from the main ruleset, enclose the anchor rules in a brace-delimited block:
-<​sxh ​pf>+<​sxh ​bash>
 anchor "​goodguys"​ { anchor "​goodguys"​ {
         pass in proto tcp from 192.168.2.3 to port 22         pass in proto tcp from 192.168.2.3 to port 22
Line 1314: Line 1314:
  
 Inline anchors can also contain more anchors. Inline anchors can also contain more anchors.
-<​sxh ​pf>+<​sxh ​bash>
 allow = "{ 192.0.2.3 192.0.2.4 }" allow = "{ 192.0.2.3 192.0.2.4 }"
  
Line 1330: Line 1330:
  
 Since anchors can be nested, it's possible to specify that all child anchors within a specified anchor be evaluated: Since anchors can be nested, it's possible to specify that all child anchors within a specified anchor be evaluated:
-<​sxh ​pf>+<​sxh ​bash>
 anchor "​spam/​*"​ anchor "​spam/​*"​
 </​sxh>​ </​sxh>​
Line 1343: Line 1343:
  
 For example: For example:
-<​sxh ​pf>+<​sxh ​bash>
 ext_if = "​fxp0"​ ext_if = "​fxp0"​
 block          on $ext_if block          on $ext_if
Line 1351: Line 1351:
  
 The rules in the anchor **ssh** are only evaluated for TCP packets destined for port 22 that come in on **fxp0**. Rules are then added to the **anchor** like so: The rules in the anchor **ssh** are only evaluated for TCP packets destined for port 22 that come in on **fxp0**. Rules are then added to the **anchor** like so:
-<​sxh ​pf>+<​sxh ​bash>
 echo "pass in from 192.0.2.10 to any" | pfctl -a ssh -f - echo "pass in from 192.0.2.10 to any" | pfctl -a ssh -f -
 </​sxh>​ </​sxh>​
Line 1358: Line 1358:
  
 The same syntax can be applied to inline anchors. The same syntax can be applied to inline anchors.
-<​sxh ​pf>+<​sxh ​bash>
 allow = "{ 192.0.2.3 192.0.2.4 }" allow = "{ 192.0.2.3 192.0.2.4 }"
 anchor "​goodguys"​ in proto tcp { anchor "​goodguys"​ in proto tcp {
Line 1375: Line 1375:
  
 To list all the rules in the anchor named **ssh**: To list all the rules in the anchor named **ssh**:
-<​sxh ​pf>+<​sxh ​bash>
 pfctl -a ssh -s rules pfctl -a ssh -s rules
 </​sxh>​ </​sxh>​
  
 To flush all rules from the same anchor: To flush all rules from the same anchor:
-<​sxh ​pf>+<​sxh ​bash>
 pfctl -a ssh -F rules pfctl -a ssh -F rules
 </​sxh>​ </​sxh>​
Line 1408: Line 1408:
 In this example, a pool of two addresses is being used to translate outgoing packets. For each outgoing connection, PF will rotate through the addresses in a round-robin manner. In this example, a pool of two addresses is being used to translate outgoing packets. For each outgoing connection, PF will rotate through the addresses in a round-robin manner.
  
-<​sxh ​pf>+<​sxh ​bash>
 match out on $ext_if inet nat-to { 192.0.2.5, 192.0.2.10 } match out on $ext_if inet nat-to { 192.0.2.5, 192.0.2.10 }
 </​sxh>​ </​sxh>​
Line 1414: Line 1414:
 One drawback with this method is that successive connections from the same internal address will not always be translated to the same translation address. This can cause interference,​ for example, when browsing websites that track user logins based on IP address. An alternate approach is to use the source-hash method so that each internal address is always translated to the same translation address. To do this, the address pool must be a [[https://​web.archive.org/​web/​20150213012421/​http://​public.swbell.net/​dedicated/​cidr.html|CIDR]] network block. One drawback with this method is that successive connections from the same internal address will not always be translated to the same translation address. This can cause interference,​ for example, when browsing websites that track user logins based on IP address. An alternate approach is to use the source-hash method so that each internal address is always translated to the same translation address. To do this, the address pool must be a [[https://​web.archive.org/​web/​20150213012421/​http://​public.swbell.net/​dedicated/​cidr.html|CIDR]] network block.
  
-<​sxh ​pf>+<​sxh ​bash>
 match out on $ext_if inet nat-to 192.0.2.4/​31 source-hash match out on $ext_if inet nat-to 192.0.2.4/​31 source-hash
 </​sxh>​ </​sxh>​
Line 1424: Line 1424:
 Address pools can also be used to load balance incoming connections. For example, incoming web server connections can be distributed across a web server farm: Address pools can also be used to load balance incoming connections. For example, incoming web server connections can be distributed across a web server farm:
  
-<​sxh ​pf>+<​sxh ​bash>
 web_servers = "{ 10.0.0.10, 10.0.0.11, 10.0.0.13 }" web_servers = "{ 10.0.0.10, 10.0.0.11, 10.0.0.13 }"
  
Line 1440: Line 1440:
  
 The following example balances outgoing traffic across two Internet connections:​ The following example balances outgoing traffic across two Internet connections:​
-<​sxh ​pf>+<​sxh ​bash>
 lan_net = "​192.168.0.0/​24"​ lan_net = "​192.168.0.0/​24"​
 int_if ​ = "​dc0"​ int_if ​ = "​dc0"​
Line 1455: Line 1455:
  
 To ensure that packets with a source address belonging to **$ext_if1** are always routed to **$ext_gw1** (and similarly for **$ext_if2** and **$ext_gw2**),​ the following two lines should be included in the ruleset: To ensure that packets with a source address belonging to **$ext_if1** are always routed to **$ext_gw1** (and similarly for **$ext_if2** and **$ext_gw2**),​ the following two lines should be included in the ruleset:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on $ext_if1 from $ext_if2 route-to ($ext_if2 $ext_gw2) pass out on $ext_if1 from $ext_if2 route-to ($ext_if2 $ext_gw2)
 pass out on $ext_if2 from $ext_if1 route-to ($ext_if1 $ext_gw1) pass out on $ext_if2 from $ext_if1 route-to ($ext_if1 $ext_gw1)
Line 1461: Line 1461:
  
 Finally, NAT can also be used on each outgoing interface: Finally, NAT can also be used on each outgoing interface:
-<​sxh ​pf>+<​sxh ​bash>
 match out on $ext_if1 from $lan_net nat-to ($ext_if1) match out on $ext_if1 from $lan_net nat-to ($ext_if1)
 match out on $ext_if2 from $lan_net nat-to ($ext_if2) match out on $ext_if2 from $lan_net nat-to ($ext_if2)
Line 1467: Line 1467:
  
 A complete example that load balances outgoing traffic might look something like this: A complete example that load balances outgoing traffic might look something like this:
-<​sxh ​pf>+<​sxh ​bash>
 lan_net = "​192.168.0.0/​24"​ lan_net = "​192.168.0.0/​24"​
 int_if ​ = "​dc0"​ int_if ​ = "​dc0"​
Line 1515: Line 1515:
  
 To add a tag to a packet, use the tag keyword: To add a tag to a packet, use the tag keyword:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on $int_if all tag INTERNAL_NET pass in on $int_if all tag INTERNAL_NET
 </​sxh>​ </​sxh>​
Line 1522: Line 1522:
  
 A tag can also be assigned using a [[openbsd_pf_users_guide_en#​macros|macro]]. For instance: A tag can also be assigned using a [[openbsd_pf_users_guide_en#​macros|macro]]. For instance:
-<​sxh ​pf>+<​sxh ​bash>
 name = "​INTERNAL_NET"​ name = "​INTERNAL_NET"​
 pass in on $int_if all tag $name pass in on $int_if all tag $name
Line 1547: Line 1547:
  
 Take the following ruleset as an example. Take the following ruleset as an example.
-<​sxh ​pf>+<​sxh ​bash>
 pass in on $int_if tag INT_NET pass in on $int_if tag INT_NET
 pass in quick on $int_if proto tcp to port 80 tag INT_NET_HTTP pass in quick on $int_if proto tcp to port 80 tag INT_NET_HTTP
Line 1560: Line 1560:
  
 To check for previously applied tags, use the tagged keyword: To check for previously applied tags, use the tagged keyword:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on $ext_if tagged INT_NET pass out on $ext_if tagged INT_NET
 </​sxh>​ </​sxh>​
  
 Outgoing packets on **$ext_if** must be tagged with the **INT_NET** tag in order to match the above rule. Inverse matching can also be done by using the ! operator: Outgoing packets on **$ext_if** must be tagged with the **INT_NET** tag in order to match the above rule. Inverse matching can also be done by using the ! operator:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on $ext_if ! tagged WIFI_NET pass out on $ext_if ! tagged WIFI_NET
 </​sxh>​ </​sxh>​
Line 1582: Line 1582:
  
 Rules now need to be written to classify packets into the policy. Rules now need to be written to classify packets into the policy.
-<​sxh ​pf>+<​sxh ​bash>
 block all block all
 pass out on $ext_if inet tag LAN_INET_NAT tagged LAN_INET nat-to ($ext_if) pass out on $ext_if inet tag LAN_INET_NAT tagged LAN_INET nat-to ($ext_if)
Line 1592: Line 1592:
  
 Now the rules that define the policy are set. Now the rules that define the policy are set.
-<​sxh ​pf>+<​sxh ​bash>
 pass in  quick on $ext_if tagged SPAMD pass in  quick on $ext_if tagged SPAMD
 pass out quick on $ext_if tagged LAN_INET_NAT pass out quick on $ext_if tagged LAN_INET_NAT
Line 1600: Line 1600:
  
 Now that the whole ruleset is setup, changes are a matter of modifying the classification rules. For example, if a POP3/SMTP server is added to the DMZ, it will be necessary to add classification rules for POP3 and SMTP traffic, like so: Now that the whole ruleset is setup, changes are a matter of modifying the classification rules. For example, if a POP3/SMTP server is added to the DMZ, it will be necessary to add classification rules for POP3 and SMTP traffic, like so:
-<​sxh ​pf>+<​sxh ​bash>
 mail_server = "​192.168.0.10"​ mail_server = "​192.168.0.10"​
 [...] [...]
Line 1609: Line 1609:
  
 The complete ruleset: The complete ruleset:
-<​sxh ​pf>+<​sxh ​bash>
 # macros # macros
 int_if ​     = "​dc0"​ int_if ​     = "​dc0"​
Line 1639: Line 1639:
 Tagging can be performed at the ethernet level if the machine doing the tagging/​filtering is also acting as a [[http://​man.openbsd.org/​bridge.4|bridge(4)]]. By creating bridge(4) filter rules that use the tag keyword, PF can be made to filter based on the source or destination MAC address. Bridge(4) rules are created using the [[http://​man.openbsd.org/​ifconfig|ifconfig(8)]] command. Example: Tagging can be performed at the ethernet level if the machine doing the tagging/​filtering is also acting as a [[http://​man.openbsd.org/​bridge.4|bridge(4)]]. By creating bridge(4) filter rules that use the tag keyword, PF can be made to filter based on the source or destination MAC address. Bridge(4) rules are created using the [[http://​man.openbsd.org/​ifconfig|ifconfig(8)]] command. Example:
  
-<​sxh ​pf>+<​sxh ​bash>
 ifconfig bridge0 rule pass in on fxp0 src 0:​de:​ad:​be:​ef:​0 tag USER1 ifconfig bridge0 rule pass in on fxp0 src 0:​de:​ad:​be:​ef:​0 tag USER1
 </​sxh>​ </​sxh>​
  
 And then in pf.conf: And then in pf.conf:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on fxp0 tagged USER1 pass in on fxp0 tagged USER1
 </​sxh>​ </​sxh>​
Line 1650: Line 1650:
 ==== DQS PF.CONF example using TAGs ==== ==== DQS PF.CONF example using TAGs ====
  
-<​sxh ​pf>+<​sxh ​bash>
 vim /​etc/​pf.conf vim /​etc/​pf.conf
 #       ​$OpenBSD:​ pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $ #       ​$OpenBSD:​ pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
Line 1766: Line 1766:
  
 Options are given in parenthesis after the log keyword; multiple options can be separated by a comma or space. Options are given in parenthesis after the log keyword; multiple options can be separated by a comma or space.
-<​sxh ​pf>+<​sxh ​bash>
 pass in log (all, to pflog1) on $ext_if inet proto tcp to $ext_if port 22 keep state pass in log (all, to pflog1) on $ext_if inet proto tcp to $ext_if port 22 keep state
 </​sxh>​ </​sxh>​
Line 1775: Line 1775:
  
 To view the log file: To view the log file:
-<​sxh ​pf>+<​sxh ​bash>
 tcpdump -n -e -ttt -r /​var/​log/​pflog tcpdump -n -e -ttt -r /​var/​log/​pflog
 </​sxh>​ </​sxh>​
  
 Note that using [[http://​man.openbsd.org/​tcpdump|tcpdump(8)]] to watch the pflog file does not give a real-time display. A real-time display of logged packets is achieved by using the pflog0 interface: Note that using [[http://​man.openbsd.org/​tcpdump|tcpdump(8)]] to watch the pflog file does not give a real-time display. A real-time display of logged packets is achieved by using the pflog0 interface:
-<​sxh ​pf>+<​sxh ​bash>
 tcpdump -n -e -ttt -i pflog0 tcpdump -n -e -ttt -i pflog0
 </​sxh>​ </​sxh>​
Line 1791: Line 1791:
  
 Because pflogd logs in tcpdump binary format, the full range of tcpdump features can be used when reviewing the logs. For example, to only see packets that match a certain port: Because pflogd logs in tcpdump binary format, the full range of tcpdump features can be used when reviewing the logs. For example, to only see packets that match a certain port:
-<​sxh ​pf>+<​sxh ​bash>
 tcpdump -n -e -ttt -r /​var/​log/​pflog port 80 tcpdump -n -e -ttt -r /​var/​log/​pflog port 80
 </​sxh>​ </​sxh>​
  
 This can be further refined by limiting the display of packets to a certain host and port combination:​ This can be further refined by limiting the display of packets to a certain host and port combination:​
-<​sxh ​pf>+<​sxh ​bash>
 tcpdump -n -e -ttt -r /​var/​log/​pflog port 80 and host 192.168.1.3 tcpdump -n -e -ttt -r /​var/​log/​pflog port 80 and host 192.168.1.3
 </​sxh>​ </​sxh>​
  
 The same idea can be applied when reading from the pflog0 interface: The same idea can be applied when reading from the pflog0 interface:
-<​sxh ​pf>+<​sxh ​bash>
 tcpdump -n -e -ttt -i pflog0 host 192.168.4.2 tcpdump -n -e -ttt -i pflog0 host 192.168.4.2
 </​sxh>​ </​sxh>​
Line 1821: Line 1821:
  
 Example: Example:
-<​sxh ​pf>+<​sxh ​bash>
 tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0 tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0
 </​sxh>​ </​sxh>​
Line 1832: Line 1832:
  
 Create the following script as **/​etc/​pflogrotate**. Create the following script as **/​etc/​pflogrotate**.
-<​sxh ​pf>+<​sxh ​bash>
 #!/bin/sh #!/bin/sh
 PFLOG=/​var/​log/​pflog PFLOG=/​var/​log/​pflog
Line 1847: Line 1847:
  
 Edit root's cron table: Edit root's cron table:
-<​sxh ​pf>+<​sxh ​bash>
 crontab -u root -e crontab -u root -e
 </​sxh>​ </​sxh>​
  
 Add the following two lines: Add the following two lines:
-<​sxh ​pf>+<​sxh ​bash>
 # rotate pf log file every 5 minutes # rotate pf log file every 5 minutes
 0-59/5 *       ​* ​      ​* ​      ​* ​      /​bin/​sh /​etc/​pflogrotate 0-59/5 *       ​* ​      ​* ​      ​* ​      /​bin/​sh /​etc/​pflogrotate
Line 1858: Line 1858:
  
 Add the following line to **/​etc/​syslog.conf**:​ Add the following line to **/​etc/​syslog.conf**:​
-<​sxh ​pf>+<​sxh ​bash>
 local0.info ​    /​var/​log/​pflog.txt local0.info ​    /​var/​log/​pflog.txt
 </​sxh>​ </​sxh>​
  
 If you also want to log to a remote log server, add the line: If you also want to log to a remote log server, add the line:
-<​sxh ​pf>+<​sxh ​bash>
 local0.info ​    ​@syslogger local0.info ​    ​@syslogger
 </​sxh>​ </​sxh>​
Line 1870: Line 1870:
  
 Create the file /​var/​log/​pflog.txt to allow syslog to log to that file, and give it the same permissions as the pflog file. Create the file /​var/​log/​pflog.txt to allow syslog to log to that file, and give it the same permissions as the pflog file.
-<​sxh ​pf>+<​sxh ​bash>
 touch /​var/​log/​pflog.txt touch /​var/​log/​pflog.txt
 chmod 600 /​var/​log/​pflog.txt chmod 600 /​var/​log/​pflog.txt
Line 1876: Line 1876:
  
 Make syslogd notice the changes by restarting it: Make syslogd notice the changes by restarting it:
-<​sxh ​pf>+<​sxh ​bash>
 kill -HUP $(cat /​var/​run/​syslog.pid) kill -HUP $(cat /​var/​run/​syslog.pid)
 </​sxh>​ </​sxh>​
Line 1884: Line 1884:
 The script **/​etc/​pflogrotate** now processes and then deletes **/​var/​log/​pflog** so rotation of pflog by [[http://​man.openbsd.org/​newsyslog|newsyslog(8)]] is no longer necessary and should be disabled. However, **/​var/​log/​pflog.txt** replaces **/​var/​log/​pflog** and rotation of it should be activated. Change **/​etc/​newsyslog.conf** as follows: The script **/​etc/​pflogrotate** now processes and then deletes **/​var/​log/​pflog** so rotation of pflog by [[http://​man.openbsd.org/​newsyslog|newsyslog(8)]] is no longer necessary and should be disabled. However, **/​var/​log/​pflog.txt** replaces **/​var/​log/​pflog** and rotation of it should be activated. Change **/​etc/​newsyslog.conf** as follows:
  
-<​sxh ​pf>+<​sxh ​bash>
 #/​var/​log/​pflog ​      ​600 ​   3    250    *    ZB "pkill -HUP -u root -U root -t - -x pflogd"​ #/​var/​log/​pflog ​      ​600 ​   3    250    *    ZB "pkill -HUP -u root -U root -t - -x pflogd"​
 /​var/​log/​pflog.txt ​   600    7    *      24 /​var/​log/​pflog.txt ​   600    7    *      24
Line 1936: Line 1936:
  
 To activate it, put something like this early in the rules section of **pf.conf**:​ To activate it, put something like this early in the rules section of **pf.conf**:​
-<​sxh ​pf>+<​sxh ​bash>
 pass in quick on $int_if inet proto tcp to port 21 divert-to 127.0.0.1 port 8021 pass in quick on $int_if inet proto tcp to port 21 divert-to 127.0.0.1 port 8021
 </​sxh>​ </​sxh>​
Line 1943: Line 1943:
  
 You also need an anchor in the rules section: You also need an anchor in the rules section:
-<​sxh ​pf>+<​sxh ​bash>
 anchor "​ftp-proxy/​*"​ anchor "​ftp-proxy/​*"​
 </​sxh>​ </​sxh>​
  
 The proxy server has to be started and running on the OpenBSD box. The proxy server has to be started and running on the OpenBSD box.
-<​sxh ​pf>+<​sxh ​bash>
 rcctl enable ftpproxy rcctl enable ftpproxy
 rcctl start  ftpproxy rcctl start  ftpproxy
Line 1972: Line 1972:
  
 In this case, PF is running on the FTP server itself rather than a dedicated firewall computer. When servicing a passive FTP connection, FTP will use a randomly chosen, high TCP port for incoming data. By default, OpenBSD'​s native [[http://​man.openbsd.org/​ftpd|ftpd(8)]] uses the range 49152 to 65535. Obviously, these must be passed through the filter rules, along with port 21 (the FTP control port): In this case, PF is running on the FTP server itself rather than a dedicated firewall computer. When servicing a passive FTP connection, FTP will use a randomly chosen, high TCP port for incoming data. By default, OpenBSD'​s native [[http://​man.openbsd.org/​ftpd|ftpd(8)]] uses the range 49152 to 65535. Obviously, these must be passed through the filter rules, along with port 21 (the FTP control port):
-<​sxh ​pf>+<​sxh ​bash>
 pass in on $ext_if proto tcp to port 21 pass in on $ext_if proto tcp to port 21
 pass in on $ext_if proto tcp to port > 49151 pass in on $ext_if proto tcp to port > 49151
Line 1984: Line 1984:
  
 [[http://​man.openbsd.org/​ftp-proxy|ftp-proxy(8)]] can be run in a mode that causes it to forward all FTP connections to a specific FTP server. Basically, we'll set up the proxy to listen on port 21 of the firewall and forward all connections to the backend server. [[http://​man.openbsd.org/​ftp-proxy|ftp-proxy(8)]] can be run in a mode that causes it to forward all FTP connections to a specific FTP server. Basically, we'll set up the proxy to listen on port 21 of the firewall and forward all connections to the backend server.
-<​sxh ​pf>+<​sxh ​bash>
 rcctl set ftpproxy flags -R 10.10.10.1 -p 21 -b 192.168.0.1 rcctl set ftpproxy flags -R 10.10.10.1 -p 21 -b 192.168.0.1
 </​sxh>​ </​sxh>​
Line 1991: Line 1991:
  
 Now for the pf.conf rules: Now for the pf.conf rules:
-<​sxh ​pf>+<​sxh ​bash>
 ext_ip = "​192.168.0.1"​ ext_ip = "​192.168.0.1"​
 ftp_ip = "​10.10.10.1"​ ftp_ip = "​10.10.10.1"​
Line 2014: Line 2014:
  
 [[http://​man.openbsd.org/​tftp-proxy|tftp-proxy(8)]] is setup in much the same way as [[http://​man.openbsd.org/​ftp-proxy|ftp-proxy(8)]] was in the [[openbsd_pf_users_guide_en#​ftp_client_behind_the_firewall|FTP client behind the firewall]] section above. [[http://​man.openbsd.org/​tftp-proxy|tftp-proxy(8)]] is setup in much the same way as [[http://​man.openbsd.org/​ftp-proxy|ftp-proxy(8)]] was in the [[openbsd_pf_users_guide_en#​ftp_client_behind_the_firewall|FTP client behind the firewall]] section above.
-<​sxh ​pf>+<​sxh ​bash>
 match out on $ext_if inet from $int_if nat-to ($ext_if) match out on $ext_if inet from $int_if nat-to ($ext_if)
 anchor "​tftp-proxy/​*"​ anchor "​tftp-proxy/​*"​
Line 2025: Line 2025:
  
 The last step is to enable tftp-proxy in [[http://​man.openbsd.org/​inetd.conf|inetd.conf(5)]] so that it listens on the same port that the divert-to rule specified above, in this case 6969. The last step is to enable tftp-proxy in [[http://​man.openbsd.org/​inetd.conf|inetd.conf(5)]] so that it listens on the same port that the divert-to rule specified above, in this case 6969.
-<​sxh ​pf>+<​sxh ​bash>
 127.0.0.1:​6969 ​ dgram   ​udp ​  ​wait ​ root  /​usr/​libexec/​tftp-proxy tftp-proxy 127.0.0.1:​6969 ​ dgram   ​udp ​  ​wait ​ root  /​usr/​libexec/​tftp-proxy tftp-proxy
 </​sxh>​ </​sxh>​
Line 2038: Line 2038:
  
 A user's rules are loaded into a unique [[openbsd_pf_users_guide_en#​anchors|anchor]] point by authpf. The anchor is named by combining the username and the authpf process-id in the username(PID) format. Each user's anchor is stored within the **authpf** [[openbsd_pf_users_guide_en#​anchors|anchor]] which is in turn anchored to the main ruleset. The fully qualified anchor path then becomes: A user's rules are loaded into a unique [[openbsd_pf_users_guide_en#​anchors|anchor]] point by authpf. The anchor is named by combining the username and the authpf process-id in the username(PID) format. Each user's anchor is stored within the **authpf** [[openbsd_pf_users_guide_en#​anchors|anchor]] which is in turn anchored to the main ruleset. The fully qualified anchor path then becomes:
-<​sxh ​pf>+<​sxh ​bash>
 main_ruleset/​authpf/​username(PID) main_ruleset/​authpf/​username(PID)
 </​sxh>​ </​sxh>​
Line 2069: Line 2069:
  
 You can link authpf into the main ruleset by using an anchor rule: You can link authpf into the main ruleset by using an anchor rule:
-<​sxh ​pf>+<​sxh ​bash>
 anchor "​authpf/​*"​ anchor "​authpf/​*"​
 </​sxh>​ </​sxh>​
Line 2091: Line 2091:
  
 In addition to the $user_ip macro, authpf will make use of the **authpf_users** table (if it exists) for storing the IP addresses of all authenticated users. Be sure to define the table before using it: In addition to the $user_ip macro, authpf will make use of the **authpf_users** table (if it exists) for storing the IP addresses of all authenticated users. Be sure to define the table before using it:
-<​sxh ​pf>+<​sxh ​bash>
 table <​authpf_users>​ persist table <​authpf_users>​ persist
 pass in on $ext_if proto tcp from <​authpf_users>​ to port smtp pass in on $ext_if proto tcp from <​authpf_users>​ to port smtp
Line 2109: Line 2109:
  
 Whenever a user successfully authenticates to authpf, a greeting is printed which indicates that the user is authenticated. Whenever a user successfully authenticates to authpf, a greeting is printed which indicates that the user is authenticated.
-<​sxh ​pf>+<​sxh ​bash>
 Hello charlie. You are authenticated from host "​198.51.100.10"​ Hello charlie. You are authenticated from host "​198.51.100.10"​
 </​sxh>​ </​sxh>​
Line 2131: Line 2131:
  
 Login classes are created in the [[http://​man.openbsd.org/​login.conf|login.conf(5)]] file. OpenBSD comes with an authpf login class defined as: Login classes are created in the [[http://​man.openbsd.org/​login.conf|login.conf(5)]] file. OpenBSD comes with an authpf login class defined as:
-<​sxh ​pf>+<​sxh ​bash>
 authpf:\ authpf:\
     :​welcome=/​etc/​motd.authpf:​\     :​welcome=/​etc/​motd.authpf:​\
Line 2143: Line 2143:
  
 Once a user has successfully logged in and authpf has adjusted the PF rules, authpf changes its process title to indicate the username and IP address of the logged in user: Once a user has successfully logged in and authpf has adjusted the PF rules, authpf changes its process title to indicate the username and IP address of the logged in user:
-<​sxh ​pf>+<​sxh ​bash>
 ps -ax | grep authpf ps -ax | grep authpf
 23664 p0  Is+     ​0:​00.11 -authpf: charlie@192.168.1.3 (authpf) 23664 p0  Is+     ​0:​00.11 -authpf: charlie@192.168.1.3 (authpf)
Line 2149: Line 2149:
  
 Here the user charlie is logged in from the machine 192.168.1.3. By sending a SIGTERM signal to the authpf process, the user can be forcefully logged out. Any rules loaded for the user will be removed and any stateful connections the user has open will be killed. Here the user charlie is logged in from the machine 192.168.1.3. By sending a SIGTERM signal to the authpf process, the user can be forcefully logged out. Any rules loaded for the user will be removed and any stateful connections the user has open will be killed.
-<​sxh ​pf>+<​sxh ​bash>
 kill -TERM 23664 kill -TERM 23664
 </​sxh>​ </​sxh>​
Line 2168: Line 2168:
  
 The **/​etc/​authpf/​authpf.rules** file contains the following rules: The **/​etc/​authpf/​authpf.rules** file contains the following rules:
-<​sxh ​pf>+<​sxh ​bash>
 wifi_if = "​wi0"​ wifi_if = "​wi0"​
  
Line 2177: Line 2177:
 The administrative user charlie needs to be able to access the campus SMTP and POP3 servers in addition to surfing the web and using SSH. The following rules are set up in **/​etc/​authpf/​users/​charlie/​authpf.rules**:​ The administrative user charlie needs to be able to access the campus SMTP and POP3 servers in addition to surfing the web and using SSH. The following rules are set up in **/​etc/​authpf/​users/​charlie/​authpf.rules**:​
  
-<​sxh ​pf>+<​sxh ​bash>
 wifi_if = "​wi0"​ wifi_if = "​wi0"​
 smtp_server = "​10.0.1.50"​ smtp_server = "​10.0.1.50"​
Line 2191: Line 2191:
  
 The main ruleset<​nowiki>​ -- </​nowiki>​located in **/​etc/​pf.conf** <​nowiki>​--</​nowiki>​ is set up as follows: The main ruleset<​nowiki>​ -- </​nowiki>​located in **/​etc/​pf.conf** <​nowiki>​--</​nowiki>​ is set up as follows:
-<​sxh ​pf>+<​sxh ​bash>
 wifi_if = "​wi0"​ wifi_if = "​wi0"​
 ext_if ​ = "​fxp0"​ ext_if ​ = "​fxp0"​
Line 2242: Line 2242:
  
 Since CARP is its own protocol, it should have an explicit pass rule in filter rulesets: Since CARP is its own protocol, it should have an explicit pass rule in filter rulesets:
-<​sxh ​pf>+<​sxh ​bash>
 pass out on $carp_dev proto carp keep state pass out on $carp_dev proto carp keep state
 </​sxh>​ </​sxh>​
Line 2326: Line 2326:
   - Use the [[http://​man.openbsd.org/​ifconfig|ifconfig(8)]] syncpeer option (see below) so that updates are unicast directly to the peer, then configure [[http://​man.openbsd.org/​ipsec|ipsec(4)]] between the hosts to secure the [[http://​man.openbsd.org/​pfsync|pfsync(4)]] traffic.   - Use the [[http://​man.openbsd.org/​ifconfig|ifconfig(8)]] syncpeer option (see below) so that updates are unicast directly to the peer, then configure [[http://​man.openbsd.org/​ipsec|ipsec(4)]] between the hosts to secure the [[http://​man.openbsd.org/​pfsync|pfsync(4)]] traffic.
 When updates are being sent and received on the network, pfsync packets should be passed in the filter ruleset: When updates are being sent and received on the network, pfsync packets should be passed in the filter ruleset:
-<​sxh ​pf>+<​sxh ​bash>
 pass on $sync_if proto pfsync pass on $sync_if proto pfsync
 </​sxh>​ </​sxh>​
Line 2541: Line 2541:
  
 **Filter the physical interface**. As far as PF is concerned, network traffic comes from the physical interface, not the CARP virtual interface (i.e., carp0). So, write your rule sets accordingly. Don't forget that an interface name in a PF rule can be either the name of a physical interface or an address associated with that interface. For example, this rule could be correct: **Filter the physical interface**. As far as PF is concerned, network traffic comes from the physical interface, not the CARP virtual interface (i.e., carp0). So, write your rule sets accordingly. Don't forget that an interface name in a PF rule can be either the name of a physical interface or an address associated with that interface. For example, this rule could be correct:
-<​sxh ​pf>+<​sxh ​bash>
 pass in on fxp0 inet proto tcp from any to carp0 port 22 pass in on fxp0 inet proto tcp from any to carp0 port 22
 </​sxh>​ </​sxh>​