Macos NAT2: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 6 промежуточных версий этого же участника)
Строка 7: Строка 7:
 
** <code>-> (utun0), а не -> utun0 </code>
 
** <code>-> (utun0), а не -> utun0 </code>
 
* вынесите правила в отдельный anchor-файл и подключить его из <code>pf.conf</code>
 
* вынесите правила в отдельный anchor-файл и подключить его из <code>pf.conf</code>
  +
  +
=Что такое «якорь» (anchor) в pf?=
  +
  +
Это контейнер/группа правил внутри дерева pf.
  +
Нужен, чтобы модульно подключать свои правила, не правя системный /etc/pf.conf.
  +
  +
В macOS есть три дерева: фильтры, NAT и RDR. Для них существуют разные «точки вставки»:
  +
  +
<PRE>
  +
anchor "name/*" — для фильтров (pass/block).
  +
nat-anchor "name/*" — для NAT.
  +
rdr-anchor "name/*" — для RDR (перенаправления/порт-форварда).
  +
</PRE>
  +
Обычно в /etc/pf.conf объявляют точки вставки и подключают файл:
  +
<PRE>
  +
anchor "nat-utun-cato/*"
  +
nat-anchor "nat-utun-cato/*"
  +
rdr-anchor "nat-utun-cato/*"
  +
load anchor "nat-utun-cato" from "/etc/pf.anchors/nat-utun-cato"
  +
</PRE>
  +
  +
=RDR=
  +
rdr = redirect — это перенаправление адреса/порта (по сути DNAT/порт-форвардинг).
  +
<BR>
  +
Применяется обычно на входящем интерфейсе: «если пришло на такой адрес/порт — отправь на другой адрес/порт».
  +
  +
Примеры:
  +
  +
* Проброс внешнего 2222 на локальный SSH:
  +
<PRE>
  +
rdr on $EXT_IF proto tcp from any to ($EXT_IF) port 2222 -> 127.0.0.1 port 22
  +
</PRE>
  +
  +
* Порт-форвард с интерфейса LAN на внутренний хост:
  +
<PRE>
  +
rdr on en0 proto tcp from any to 192.168.22.1 port 8443 -> 192.168.22.10 port 443
  +
</PRE>
  +
  +
Важно: rdr не автоматически разрешает трафик. Нужен соответствующий pass
  +
  +
==Отличия nat vs rdr==
  +
  +
* NAT: меняет исходный адрес при исходящем трафике (SNAT/маскарадинг), напр. nat on $VPN_IF ... -> ($VPN_IF).
  +
* RDR: меняет целевой адрес/порт при входящем трафике (DNAT/порт-форвард), напр. rdr on $EXT_IF ... -> 192.168.22.10 port 22.
   
 
=Отдельный файл с NAT=
 
=Отдельный файл с NAT=
Строка 34: Строка 78:
 
=Подключить anchor из <code>pf.conf</code>=
 
=Подключить anchor из <code>pf.conf</code>=
   
/etc/pf.conf (добавьте строки, не ломая apple-якоря):
+
<code>/etc/pf.conf</code> (добавьте строки, не ломая apple-якоря):
  +
<PRE>
  +
anchor "nat-utun-cato"
  +
load anchor "nat-utun-cato" from "/etc/pf.anchors/nat-utun-cato"
  +
</PRE>
   
  +
=Включите форвардинг разово=
anchor "nat-utun"
 
  +
до перезагрузки
load anchor "nat-utun" from "/etc/pf.anchors/nat-utun"
 
 
Включите форвардинг разово (до перезагрузки):
 
 
<PRE>
 
<PRE>
 
sudo sysctl -w net.inet.ip.forwarding=1
 
sudo sysctl -w net.inet.ip.forwarding=1
 
</PRE>
 
</PRE>
   
  +
=Полезно=
  +
  +
Стаус глобально
  +
<PRE>
  +
sudo pfctl -si
  +
</PRE>
  +
  +
включить pf (если был выключен)
  +
<PRE>
  +
sudo pfctl -e
  +
</PRE>
   
 
проверка синтаксиса
 
проверка синтаксиса
  +
<PRE>
 
sudo pfctl -nf /etc/pf.conf
 
sudo pfctl -nf /etc/pf.conf
  +
</PRE>
  +
 
загрузить правила
 
загрузить правила
  +
<PRE>
 
sudo pfctl -f /etc/pf.conf
 
sudo pfctl -f /etc/pf.conf
  +
</PRE>
sudo pfctl -e # включить pf (если был выключен)
 
  +
Лучше с отладкой
sudo pfctl -sn # посмотреть NAT-правила
 
  +
<PRE>
sudo pfctl -s state -v | head # посмотреть состояния/NAT
 
  +
pfctl -v -f /etc/pf.conf
  +
</PRE>
   
Что с изменениями адреса/интерфейса
 
   
  +
посмотреть NAT-правила
Меняется IP на том же utun0 — ничего делать не нужно: -> (utun0) подхватит новый адрес автоматически.
 
  +
<PRE>
  +
sudo pfctl -sn
  +
</PRE>
   
  +
посмотреть состояния/NAT
Меняется сам номер интерфейса (utun0 → utun2) — правила с $VPN_IF="utun0" уже не совпадут. Варианты:
 
  +
<PRE>
 
  +
sudo pfctl -s state -v
Постараться закрепить один и тот же utun в вашем VPN-клиенте (часто получается).
 
  +
</PRE>
 
Лёгкий «апдейтер» интерфейса + перезагрузка pf на событие «VPN поднялся». Пример одноразовой команды, если нужно быстро переключиться:
 
 
VPN_IF=$(ifconfig -l | tr ' ' '\n' | awk '/^utun[0-9]+$/ {print; exit}')
 
sudo sed -i '' "s/^VPN_IF.*/VPN_IF = \"$VPN_IF\"/" /etc/pf.anchors/nat-utun
 
sudo pfctl -f /etc/pf.conf
 
   
  +
# Все фильтрующие правила (pass/block) из всех якорей
  +
sudo pfctl -sr -a '*'
   
  +
# Все NAT и RDR из всех якорей
(Можно оформить это как скрипт «PostUp» вашего VPN-клиента.)
 
  +
sudo pfctl -sn -a '*'
   
  +
# Более подробный вывод (интерфейсы, счётчики, метки)
Частые грабли
 
  +
sudo pfctl -v -sr -a '*'
  +
sudo pfctl -v -sn -a '*'
   
  +
# Показать список загруженных якорей (навигация)
Забытый () в -> (utun0) — именно тогда NAT «забывает» новый IP.
 
  +
sudo pfctl -s anchors
   
  +
# Показать только Apple-правила (пример)
Нет net.inet.ip.forwarding=1 — клиенты из 192.168.22.0/24 не ходят «наружу».
 
  +
sudo pfctl -sr -a 'com.apple/*'
  +
sudo pfctl -sn -a 'com.apple/*'
  +
Замечания:
   
  +
«Совсем без привязки к якорям» как плоский единый список у pfctl нет — но -a '*' по сути раскрывает всё дерево.
Неправильно выбран LAN-интерфейс в pass in on … — форвардинг режется фильтром.
 
   
  +
-sr — фильтр (rules), -sn — NAT/RDR. Для полного обзора запустите оба.
MDM/профили могут запрещать менять pf/форвардинг — тогда только через администратора.
 
   
  +
Сообщение про ALTQ можно игнорировать на macOS (ALTQ не используется).
Если скажете, какой у вас LAN-интерфейс (en0/en1/bridge0 и т.п.) и кто «вешает» VPN (WireGuard/OpenVPN/встроенный IKEv2), накину точный блок pass in/out и, при желании, минимальный launchd plist для автоприменения.
 

Текущая версия на 13:16, 21 октября 2025


Mac OS NAT V2

Это порсто проверенный пример который работает, без особых подробностей

  • pf нужно использовать динамическую подстановку адреса интерфейса — так NAT «подтянет» новый IP при переподключении VPN.
    • -> (utun0), а не -> utun0
  • вынесите правила в отдельный anchor-файл и подключить его из pf.conf

Что такое «якорь» (anchor) в pf?

Это контейнер/группа правил внутри дерева pf. Нужен, чтобы модульно подключать свои правила, не правя системный /etc/pf.conf.

В macOS есть три дерева: фильтры, NAT и RDR. Для них существуют разные «точки вставки»:

anchor "name/*" — для фильтров (pass/block).
nat-anchor "name/*" — для NAT.
rdr-anchor "name/*" — для RDR (перенаправления/порт-форварда).

Обычно в /etc/pf.conf объявляют точки вставки и подключают файл:

anchor "nat-utun-cato/*"
nat-anchor "nat-utun-cato/*"
rdr-anchor "nat-utun-cato/*"
load anchor "nat-utun-cato" from "/etc/pf.anchors/nat-utun-cato"

RDR

rdr = redirect — это перенаправление адреса/порта (по сути DNAT/порт-форвардинг).
Применяется обычно на входящем интерфейсе: «если пришло на такой адрес/порт — отправь на другой адрес/порт».

Примеры:

  • Проброс внешнего 2222 на локальный SSH:
rdr on $EXT_IF proto tcp from any to ($EXT_IF) port 2222 -> 127.0.0.1 port 22
  • Порт-форвард с интерфейса LAN на внутренний хост:
rdr on en0 proto tcp from any to 192.168.22.1 port 8443 -> 192.168.22.10 port 443

Важно: rdr не автоматически разрешает трафик. Нужен соответствующий pass

Отличия nat vs rdr

  • NAT: меняет исходный адрес при исходящем трафике (SNAT/маскарадинг), напр. nat on $VPN_IF ... -> ($VPN_IF).
  • RDR: меняет целевой адрес/порт при входящем трафике (DNAT/порт-форвард), напр. rdr on $EXT_IF ... -> 192.168.22.10 port 22.

Отдельный файл с NAT

/etc/pf.anchors/nat-utun

# что транслируем - только адрес ноута
LAN_NET = "192.168.22.253/32"
VPN_IF  = "utun0"

set skip on lo0            # не трогаем localhost

# NAT: адрес берётся динамически с интерфейса (в скобках!)
nat on $VPN_IF from $LAN_NET to any -> ($VPN_IF)

# Разрешим исходящий трафик из LAN в VPN
pass out on $VPN_IF inet proto { tcp udp icmp } from $LAN_NET to any keep state

# Если Mac роутит для вашей LAN: разрешите форвардинг с LAN-интерфейса (подставьте его имя)
# Например, если клиенты заходят через Wi-Fi интерфейс en0:
pass in  on en0 inet from $LAN_NET to any keep state
pass out on $VPN_IF from $LAN_NET to any keep state

Скобки вокруг ($VPN_IF) — ключевое: pf будет автоматически использовать текущий адрес интерфейса, даже если он поменялся после переподключения VPN.

Подключить anchor из pf.conf

/etc/pf.conf (добавьте строки, не ломая apple-якоря):

anchor "nat-utun-cato"
load anchor "nat-utun-cato" from "/etc/pf.anchors/nat-utun-cato"

Включите форвардинг разово

до перезагрузки

sudo sysctl -w net.inet.ip.forwarding=1

Полезно

Стаус глобально

sudo pfctl -si 

включить pf (если был выключен)

sudo pfctl -e

проверка синтаксиса

sudo pfctl -nf /etc/pf.conf

загрузить правила

sudo pfctl -f  /etc/pf.conf

Лучше с отладкой

pfctl -v -f /etc/pf.conf  


посмотреть NAT-правила

sudo pfctl -sn

посмотреть состояния/NAT

sudo pfctl -s state -v
  1. Все фильтрующие правила (pass/block) из всех якорей

sudo pfctl -sr -a '*'

  1. Все NAT и RDR из всех якорей

sudo pfctl -sn -a '*'

  1. Более подробный вывод (интерфейсы, счётчики, метки)

sudo pfctl -v -sr -a '*' sudo pfctl -v -sn -a '*'

  1. Показать список загруженных якорей (навигация)

sudo pfctl -s anchors

  1. Показать только Apple-правила (пример)

sudo pfctl -sr -a 'com.apple/*' sudo pfctl -sn -a 'com.apple/*' Замечания:

«Совсем без привязки к якорям» как плоский единый список у pfctl нет — но -a '*' по сути раскрывает всё дерево.

-sr — фильтр (rules), -sn — NAT/RDR. Для полного обзора запустите оба.

Сообщение про ALTQ можно игнорировать на macOS (ALTQ не используется).