OpenBSD PF - Преобразование сетевых адресов (Network Address Translation) [FAQ PF - На главную]



Введение

Преобразование (или сопоставление) сетевых адресов (Network Address Translation, NAT) - это способ сопоставить всю сеть (или сети) одному IP-адресу. Это необходимо, к примеру, если количество IP-адресов, предоставленных вам вашим провайдером, меньше общего количества компьютеров, которым нужен доступ в интернет. Стандарт NAT описан в RFC 1631.

NAT позволяет администраторам воспользоваться зарезервированными адресными блоками, описанными в RFC 1918. Как правило, внутренняя сеть будет настроена на использование одного или нескольких из этих сетевых блоков.

10.0.0.0/8       (10.0.0.0 - 10.255.255.255)
172.16.0.0/12    (172.16.0.0 - 172.31.255.255)
192.168.0.0/16   (192.168.0.0 - 192.168.255.255)
OpenBSD, используемая для преобразования сетевых адресов (NAT), должна иметь как минимум два сетевых интерфейса: один для интернета, другой для внутренней сети. NAT будет транслировать запросы из внутренней сети, поэтому они будут поступать от OpenBSD системы с NAT.

Принцип работы NAT

Когда клиентская машина во внутренней сети связывается с машиной в интернете, она отправляет, предназначенные для этой машины, IP-пакеты. Эти пакеты содержат информацию, необходимую для того, чтобы удаленная машина получила их. NAT связывает такую информацию таким образом: IP-адрес клиентской машины и TCP- или UDP-порт, используемый клиентской машиной.

Когда пакеты проходят через шлюз NAT (NAT gateway), они изменяются таким образом, как будто их отправляет сам шлюз. Он записывает изменения, которые вносит в свою таблицу состояний, чтобы в последствии мог отменить изменения в возвращаемых пакетах и обеспечить, чтобы эти пакеты проходили через firewall и не блокировались. Например, могут быть сделаны следующие изменения:

Ни внутренняя клиентская машина, ни интернет-хост не знают об этих изменениях. Для клиента NAT - это просто интернет-шлюз. Для интернет-хоста пакеты, кажется, приходят непосредственно от самого шлюза. Совершенно не известно, что внутренняя клиентская машина вообще существует.

Когда интернет-хост отвечает на пакеты клиентской внутренней машины, они будут адресованы внешнему IP-адресу NAT-шлюза на выбранный для NAT-соединения порт. Затем NAT шлюз выполнит поиск таблицы состояний, чтобы определить, соответствуют ли полученные пакеты уже установленному соединению. Уникальное совпадение будет найдено на основе комбинации IP/порта, которая сообщает PF, что пакеты принадлежат соединению, инициированному внутренней (клиентской) машиной. Затем PF внесет противоположные изменения в исходящие пакеты и перенаправит ответные пакеты клиентской машине во внутренней сети.

Трансляция ICMP-пакетов происходит аналогичным образом, но естественно без изменения порта клиента.

IP перенаправление

Поскольку NAT почти всегда используется на маршрутизаторах (routers) и сетевых шлюзах (network gateways), возможно, потребуется активировать/разрешить перенаправление IP-пакетов (IP forwarding), чтобы пакеты могли быть переданы между сетевыми интерфейсами на OpenBSD машине. IP forwarding включается при помощи sysctl(2):
# sysctl net.inet.ip.forwarding=1
# echo  'net.inet.ip.forwarding=1' >> /etc/sysctl.conf
Или, если используется IPv6:
# sysctl net.inet6.ip6.forwarding=1
# echo  'net.inet6.ip6.forwarding=1' >> /etc/sysctl.conf

Настройка NAT

NAT указывается как необязательный nat-to параметр для исходящего pass правила. Часто вместо установки pass правила используется правило match. Когда пакет попадает под критерий правила match, параметры (например, nat-to) в этом правиле запоминаются и применяются к пакету, когда достигается pass правило, соответствующее пакету. Это позволяет обрабатывать целый класс пакетов с помощью одного правила match, а затем конкретные решения о разрешении трафика можно принимать с помощью правил block и pass.

На практике формат конфига pf.conf выглядит слелующим образом:

match out on interface [af] \
   from src_addr to dst_addr \
   nat-to ext_addr [pool_type] [static-port]
[...]
pass out [log] on interface [af] [proto protocol] \
   from ext_addr [port src_port] \
   to dst_addr [port dst_port]
match
Когда пакет, пробегая через правила фильтра, наконец попадает под критерий правила match, любые дополнительные параметры, указанные в этом правиле, запоминаются для будущего использования (становятся "sticky" («прикрепленными»)).

pass
Это правило разрешает передачу пакета. Если пакет ранее соответствовал match правилу, в котором были указаны параметры, они будут применены к этому пакету. Правила pass могут иметь свои собственные параметры; они имеют приоритет над параметрами, указанными в правиле match.

out
Указывает направление потока пакетов, к которому применяется это правило. nat-to можно указывать только для исходящих пакетов.

log
Регистрирует соответствующие пакеты через pflogd(8). Обычно регистрируется только первый соответствующий пакет. Чтобы зарегистрировать все соответствующие пакеты, используйте log (all).

interface
Имя или группа сетевых интерфейсов, по которым будут передаваться пакеты.

af
Семейство адресов: inet для IPv4 или inet6 для IPv6. PF обычно может определить этот параметр на основе адреса(ов) источника/назначения.

protocol
Протокол (например, tcp, udp, icmp) разрешенных пакетов. Если указан src_port или dst_port, необходимо также указать протокол.

src_addr
The source (internal) address of packets that will be translated. The source address can be specified as:

src_port
The source port in the Layer 4 packet header. Ports can be specified as: The port option is not usually used in nat rules because the goal is usually to NAT all traffic regardless of the port(s) being used.
dst_addr
The destination address of packets to be translated. The destination address is specified in the same way as the source address.
dst_port
The destination port in the Layer 4 packet header. This port is specified in the same way as the source port.
ext_addr
The external (translation) address on the NAT gateway that packets will be translated to. The external address can be specified as:
pool_type
Specifies the type of address pool to use for translation.

static-port
Tells PF not to translate the source port in TCP and UDP packets.

This would lead to a most basic form of these lines similar to this:

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
Or the following may be used:
pass out on tl0 from 192.168.1.0/24 to any nat-to 198.51.100.1
This rule says to perform NAT on the tl0 interface for any packets coming from 192.168.1.0/24 and to replace the source IP address with 198.51.100.1.

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):

pass out on tl0 inet from dc0:network to any nat-to tl0
The advantage should be fairly clear: the IP addresses of either interface can be changed without changing this rule. Note that inet should be specified in this case to ensure that only IPv4 addresses are used, avoiding unexpected surprises.

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 DHCP is being used to configure the external interface, this can be a problem. If the 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, PF can automatically update the translation address by putting parentheses around the interface name:

pass out on tl0 inet from dc0:network to any nat-to (tl0)
This method works for translation to both IPv4 and IPv6 addresses.

Bidirectional Mapping (1:1 Mapping)

A bidirectional mapping can be established by using the binat-to parameter. A binat-to rule establishes a one-to-one mapping between an internal IP address and an external address. This can be useful, for example, to provide a web server on the internal network with its own external IP address. Connections from the internet to the external address will be translated to the internal address and connections from the web server (such as DNS requests) will be translated to the external address. TCP and UDP ports are never modified with binat-to rules as they are with nat rules.

Example:

web_serv_int = "192.168.1.100"
web_serv_ext = "198.51.100.6"

pass on tl0 from $web_serv_int to any binat-to $web_serv_ext

Исключения правил трансляции

Если в некоторых случаях необходимо предоставить исключения из правил NAT, убедитесь, что исключения обрабатываются правилом фильтра, которое не включает параметр nat-to. Например, если приведенный выше пример NAT был изменен так:
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
Тогда вся сеть 192.168.1.0/24 будет транслировать пакеты на внешний адрес 198.51.100.79, за исключением 192.168.1.208.

Проверка состояния NAT

Для просмотра активных трансляций NAT используется pfctl(8) с опцией -s state. Эта опция выведет список всех текущих сеансов NAT:
# 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 udp 192.168.1.35:2491 (198.51.100.1:60527) -> 198.51.100.33:53   MULTIPLE:SINGLE
Объясним первую строку:
fxp0
Указывает интерфейс, к которому привязано состояние. Слово self появится, если состояние floating.

TCP
Протокол, используемый соединением.

192.168.1.35:2132
IP-адрес (192.168.1.35) интерфейса внутренней сети. Исходный порт (2132) отображается после адреса. Это также адрес, который заменяется (перезаписываетя) в IP-заголовке.

198.51.100.1:53136
IP-адрес (198.51.100.1) и порт (53136) на шлюзе, на который передаются пакеты.

198.51.100.10:22
IP-адрес (198.51.100.10) и порт (22), к которому подключается хост из внутренней сети.

TIME_WAIT:TIME_WAIT
Это указывает, в каком состоянии, по мнению PF, находится TCP-соединение.