Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Building Firewalls With OpenBSD And PF, 2nd Edition (2003)

.pdf
Скачиваний:
39
Добавлен:
17.08.2013
Размер:
2.74 Mб
Скачать

Section 7.3: NAT Rules

 

 

 

 

 

 

 

 

137

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Internet

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

router

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OpenBSD:

 

 

 

 

 

 

pf + bridge

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OpenBSD:

 

 

 

 

 

 

 

pf + NAT

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

joe

 

hub/switch

 

sarah

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ann

 

 

 

 

 

 

 

 

 

 

don

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

terry

 

 

 

 

 

 

 

 

 

 

julia

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Œona

 

 

 

 

 

 

 

 

 

 

marc

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 7.1: A solution to the bridge/NAT incompatibility problem.

7.3 NAT Rules

There are three kinds of NAT rules:

1.nat Š translation between groups of internal addresses and a single external address.

2.rdr Š address and port redirection.

3.binat Š bidirectional translation between one internal address and one external address.

If you plan to use NAT, you must Œrst enable IP forwarding in the OpenBSD kernel. You can learn how to do it from Chapter 4 ConŒguring OpenBSD.

Unlike packet Œltering rules, packet redirection rules are matched using the `Œrst matching rule wins' algorithm, which means that you must always put

138

Chapter 7: Packet Redirection

 

 

more speciŒc rules before more general ones. For example, consider these two rules: (1) redirect all trafŒc sent to port 80 from the outside to port 8080 on your HTTP server sitting in the DMZ, (2) redirect all trafŒc sent to port 80 from your boss' home machine to port 8888 on your HTTP server sitting in the DMZ. Unless rule (2) is placed before rule (1), it will never be matched and all trafŒc will be redirected as per rule (1).

7.3.1 Hiding Hosts Behind a Single Address with nat Rules

NAT rules perform network address translation for groups of internal hosts, with private addresses hidden behind a Œrewall, which access the outside world through a single interface with one public IP. (The external interface could have more IP addresses assigned to it.) This not only solves the problem of connecting more than one host through a single interface, but it also hides the details of your internal network's layout, the number of hosts, and other information that the intruder may Œnd useful. Hosts with private IP addresses hidden behind NAT are not reachable from the outside, all the outside world sees is a single public IP address (e.e.e.e in Figure 7.2).

The magic is possible because the Œrewall keeps a record of who sent what and where, so it can send replies to the right host. To do that it must keep a table of sorts and mark packets it sends to the Internet. This marking allows attackers to deduct how many hosts are hidden behind the Œrewall and gives them an idea of what might be going on behind it, provided they can capture that trafŒc. It is also used by companies selling DSL access to the Internet to Œnd out who's breaching their contracts. (Some DSL access providers forbid their customers to use NAT, and impose penalties on those who use it. If your provider does this, consider switching to another.) The latest versions of pf(4) can fool these detection systems, as described in Chapter 6, Packet Normalization.

NAT rules have the following syntax:

ƒThe no switch. Tells pf(4) to not perform network address translation. It is used to selectively turn redirection off for certain users or types of connections. This part is optional.

ƒThe nat keyword. This part is required.

ƒThe pass keyword. This part is optional. When you use it, the packet is sent to the destination host without matching it against the packet Œltering rules.

Section 7.3: NAT Rules

 

 

 

 

 

 

 

 

139

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Internet

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

router

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

e.e.e.e

 

 

 

 

 

 

 

pf + NAT

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a.a.a.7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a.a.a.1

 

hub/switch

 

a.a.a.8

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a.a.a.2

 

 

 

 

 

 

 

 

 

 

a.a.a.7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a.a.a.3

 

 

 

 

 

 

 

 

 

 

a.a.a.6

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

a.a.a.4

 

 

 

 

 

 

 

 

 

 

a.a.a.5

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 7.2: All connections to the outside world sent from a.a.a.a/24 hosts appear to be originating from e.e.e.e/32.

ƒThe name of the interface or the list of interfaces. Starts with the on keyword. You need to tell pf(4) which interface each nat rule applies to, so this part is required.

ƒThe name of the IP address family. Possible values are inet (for IPv4 addresses) or inet6 (for IPv6 addresses). This part is required if the target address (listed after ->) expands to more than one address family; this happens when you use the hostname or the interfae name in place of a single IPv4 or IPv6 address.

ƒProtocol speciŒcation. Discussed in Chapter 5, /etc/pf.conf.

ƒSource host(s) addresses and ports. These are addresses and ports you want to do NAT for. Addresses are discussed in Chapter 5, /etc/pf.conf.

ƒTag marker. You can mark packets translated with nat for a doublecheck Œltering with the tag keyword followed by the identiŒer string. Such packets can later be matched with the tagged keyword. This part is optional. For more information on this subject, consult Chapter 5,

/etc/pf.conf.

ƒTarget host(s) addresses and ports. These are addresses and ports that

140

Chapter 7: Packet Redirection

 

 

packets are sent to by source hosts. This syntax is used very rarely. Addresses are discussed in Chapter 5, /etc/pf.conf.

ƒExternal address used to perform NAT on.

ƒPool options. Discussed in Chapter 10, Bandwidth Shaping and Load Balancing.

ƒThe static-port option. This is optional, when you use it, NAT does not modify the source port of translated packets. It may help you with VPN setups and those connections that somehow break when you pipe them through nat rules. This part is optional.

How do you connect your private network to the outside world? It's quite simple, actually:

########################################################

# macro definitions

#-------------------------------------------------------

# ext_if --

the name of the firewalls's external

#

interface

 

ext_if = "ne1"

 

# ext_ad --

the public IPv4 address assigned to the

#

firewall's external interface

ext_ad = "e.e.e.e/32"

 

# prv_ad --

the range

of private IPv4 addresses

 

assigned to hosts on the screened LAN

prv_ad = "p.p.p.p/24"

 

# nat_proto

-- NAT-ed

protocols

nat_proto = "{tcp, udp, icmp}"

########################################################

# NAT rules: "rdr", "nat", "binat"

#-------------------------------------------------------

nat on $ext_if inet proto $nat_proto \ from $prv_ad to any -> $ext_ad

When it is time to add a new network segment, modify the macros:

########################################################

# macro definitions

#-------------------------------------------------------

Section 7.3: NAT Rules

141

 

 

# ext_if --

the name of the firewalls's external

#

interface

 

ext_if = "ne1"

 

# ext_ad --

the public

IPv4 address assigned to the

#

firewall's

external interface

ext_ad = "e.e.e.e/32"

 

# prv1_ad --

the range

of private IPv4 addresses

#

assigned to hosts on the screened LAN #1

prv1_ad = "p.p.1.p/24"

 

# prv2_ad --

the range

of private IPv4 addresses

#

assigned to hosts on the screened LAN #2

prv2_ad = "p.p.2.p/24"

 

# nat_proto

-- NAT-ed protocols

nat_proto = "{tcp, udp, icmp}"

########################################################

# NAT rules: "rdr", "nat", "binat"

#-------------------------------------------------------

nat on $ext_if inet proto $nat_proto from \ {$prv1_ad, $prv2_ad} to any -> $ext_ad

Shouldn't we use the names of the interfaces that connect our private networks to the Œrewall? No, we want the outside world to see all connections originating from the Œrewall's external IP address and that address is assigned to the Œrewall's external interface. Those two pieces of information must match.

Just like rdr rules, nat rules allow us to use the no and ! modiŒers before interface names and private host addresses. These operators have many useful applications. For example, when you translate addresses on two or more network segments, as shown above, the hosts from different segments cannot communicate with each other. To solve that, you must add another two rules before the main NAT rule:

########################################################

# macro definitions

#-------------------------------------------------------

 

# ext_if --

the name of the firewalls's external

#

interface

ext_if = "ne1"

142

Chapter 7: Packet Redirection

 

 

#ext_ad -- the public IPv4 address assigned to the

#firewall's external interface

ext_ad = "e.e.e.e/32"

#prv1_ad -- the range of private IPv4 addresses

#assigned to hosts on the screened LAN #1 prv1_ad = "p.p.1.p/24"

#prv2_ad -- the range of private IPv4 addresses

#assigned to hosts on the screened LAN #2 prv2_ad = "p.p.2.p/24"

#nat_proto -- NAT-ed protocols

nat_proto = "{tcp, udp, icmp}"

########################################################

# NAT rules: "rdr", "nat", "binat"

#-------------------------------------------------------

no nat on $ext_if inet proto $nat_proto \ from $prv1_ad to $prv2_ad

no nat on $ext_if inet proto $nat_proto \ from $prv2_ad to $prv1_ad

nat on $ext_if inet proto $nat_proto \

from {$prv1_ad, $prv2_ad} to any -> $ext_ad

The no nat rules match packets before they are matched by the nat rule and so communication between the two local network segments is enabled.

It is also possible to limit their scope to IPv4 or IPv6 packets (inet and inet6, respectively).

Not all is rosy with NAT, of course. It changes the source ports in IP packets, which some applications complain about, although this is not such a huge problem. A more serious danger is a real possibility of running out of ports on the external address. While 65535 ports is enough for a single host, there is a real possibility that it will run out when the same number of ports is shared among several dozens of hosts behind NAT as they will all use ports associated with the Œrewall's external IP address.

The solution is to assign two or more public IP addresses to the external interface using the ifconŒg(8) alias option or, to make changes permanent,

Section 7.3: NAT Rules

143

 

 

store that information in the appropriate /etc/hostname.* Œle. You'll Œnd the necessary instructions in Chapter 4, ConŒguring OpenBSD. Then, you can write two separate NAT rules that translate addresses of two different network segments on two different external addresses, even though these addresses are assigned to the same external interface on the Œrewall:

########################################################

# macro definitions

#-------------------------------------------------------

 

# ext_if --

the name of the firewalls's external

#

interface

ext_if = "ne1"

# ext1_ad --

the first public IPv4 address assigned to

#

the firewall's external interface

ext1_ad = "e.e.e.e/32"

# ext2_ad --

the second public IPv4 address assigned to

#

the firewall's external interface

ext2_ad = "e.e.e.f/32"

# prv1_ad --

the range of private IPv4 addresses

#

assigned to hosts on the screened LAN #1

prv1_ad = "p.p.1.p/24"

# prv2_ad --

the range of private IPv4 addresses

#

assigned to hosts on the screened LAN #2

prv2_ad = "p.p.2.p/24"

# nat_proto

-- NAT-ed protocols

nat_proto = "{tcp, udp, icmp}"

########################################################

# NAT rules: "rdr", "nat", "binat"

#-------------------------------------------------------

no nat $ext_if inet proto $nat_proto \ from $prv1_ad to $prv2_ad

no nat $ext_if inet proto $nat_proto \ from $prv2_ad to $prv1_ad

nat on $ext_if inet proto $nat_proto \ from $prv1_ad to any -> $ext1_ad

nat on $ext_if inet proto $nat_proto \ from $prv2_ad to any -> $ext2_ad

144

Chapter 7: Packet Redirection

 

 

What if you cannot get another public IP address? There is not much you can do about that, but you can try to divide the available port space between competing LAN segments:

nat on $ext_if inet proto $nat_proto from $prv1_ad to any \ -> $ext1_ad port 10000:20000

nat on $ext_if inet proto $nat_proto from $prv2_ad to any \ -> $ext2_ad port 20001:30000

Another issue that is sometimes problematic is the assignment of source ports. Pf(4) does it in a random way, which not all applications like. You can solve that with a NAT proxy rule that looks like this:

nat on $ext_if inet proto $nat_proto from $prv1_ad port 22 \ to any -> $ext1_ad port 8022

What if you wanted to map ports in a one-to-one fashion, 1024 to 1024, 30000 to 30000, etc.? Use the asterisk notation:

nat on $ext_if inet proto $nat_proto \

from $prv1_ad port 1024:65535 to any -> $ext1_ad port 1024:*

Such speciŒc rules go between no nat and nat rules.

It is also possible to turn off source port modiŒcations in nat rules with the static-port option placed at the very end of such rule:

nat on $ext_if inet proto $nat_proto from $prv1_ad port 22 \ to any -> $ext1_ad static-port

or:

nat on $ext_if inet proto $nat_proto from $prv1_ad \ to any -> $ext1_ad static-port

NAT rules are often used together with matching packet Œltering that either block or pass packets after they are redirected with nat, e.g.:

# NAT internal hosts on the external interface ext_if

nat on $ext_if inet proto tcp from $prv_ad to any -> ($ext_if)

Section 7.3: NAT Rules

145

 

 

# block connections to port 25 on any external host block out on $ext_if inet proto tcp \

from ($ext_if) to any port 25

You could replace these rules with a single NAT/pass rule (use the pass keyword):

nat pass on $ext_if inet proto tcp \

from $prv_ad to any port != 25 -> ($ext_if)

Another important tool that binds NAT rules with Œlter rules are tags. You can read more about them in Chapter 5, /etc/pf.conf. Please note that the pass and tag keywords don't mix. If you use the pass keyword in a nat rule and tag packets, then the packet Œltering section will be skipped and the tagged keyword will be redundant. Keep this in mind when you wonder why some rules don't match packets or when you get lost and feel overwhelemed by the complexity of your ruleset (a clear sign that you overengineered your ruleset).

Additional information about the NAT/Œltering interactions can be found in Chapter 8, Packet Filtering.

The nat rules can be replaced with other nat rules from an external source while pf(4) is running. To use that feature, you'll have to use anchors. They are especially useful in authorization with authpf(8) and you can read more about them in Chapter 9, Dynamic Rulesets, and Chapter 12,

Using authpf.

7.3.2 Redirecting Packets to Other Addresses and Ports (rdr)

The rdr rules are written using the following syntax:

ƒThe no switch. Tells pf(4) to not perform packet redirection. It is used to selectively turn redirection off for certain users or types of connections. This part is optional.

ƒThe rdr keyword. This part is required.

ƒThe pass keyword. This part is optional. When you use it, the packet is sent to the destination host without matching it against the packet Œltering rules.

ƒThe name of the interface or a list of interfaces. Starts with the on

146

Chapter 7: Packet Redirection

 

 

keyword. You need to tell pf(4) which interface each rdr rule applies to, so this part is required.

ƒThe name of the IP address family. Possible values are inet (for IPv4 addresses) or inet6 (for IPv6 addresses). This part is required if the target address (listed after ->) expands to more than one address family; this happens when you use the hostname or the interface name in place of a single IPv4 or IPv6 address.

ƒProtocol speciŒcation. Discussed in Chapter 5, /etc/pf.conf.

ƒRedirected host(s) addresses and ports. These are addresses and ports you want to redirect. Addresses are discussed in Chapter 5, /etc/pf.conf.

ƒTag marker. You can mark packets translated with rdr for a doublecheck Œltering with the tag keyword followed by the identiŒer string. Such packets can later be matched with the tagged keyword. This part is optional. For more information on this subject, consult Chapter 5,

/etc/pf.conf.

ƒTarget host(s) addresses and ports. These are addresses and ports that packets will be redirected to. Addresses are discussed in Chapter 5,

/etc/pf.conf.

ƒPool options. Discussed in Chapter 10, Bandwidth Shaping and Load

Balancing.

The rdr rules redirect packets from one port to another. A classic example of using trafŒc redirection is an HTTP server sitting in a DMZ, yet accessible to hosts outside your network as shown in Figure 7.3. Ordinarily, such server must listen on port 80, and the machine it runs on must be directly accessible to external hosts. This setup is not very safe, so you might consider moving the server behind a Œrewall, into a DMZ network segment.

However, if you do that, the HTTP server is inaccessible, because it has no public IP address and it's the Œrewall that receives requests sent to the that server instead.

The Œrewall must redirect these packets to the HTTP server residing inside the DMZ network segment. This is accomplished with the following NAT rule:

########################################################

# macro definitions

#-------------------------------------------------------

#ext_if -- the name of the firewall's external

#interface

ext_if = "ne1"