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

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 2: Строка 2:
   
 
=Mac OS NAT V2=
 
=Mac OS NAT V2=
  +
Это порсто проверенный пример который работает, без особых подробностей
  +
  +
* pf нужно использовать динамическую подстановку адреса интерфейса — так NAT «подтянет» новый IP при переподключении VPN.
  +
** <code>-> (utun0), а не -> utun0 </code>
  +
* вынесите правила в отдельный anchor-файл и подключить его из <code>pf.conf</code>
  +
  +
==Отдельный файл с NAT==
  +
  +
<code>/etc/pf.anchors/nat-utun</code>
  +
<PRE>
  +
# что транслируем - только адрес ноута
  +
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
  +
</PRE>
  +
  +
Скобки вокруг ($VPN_IF) — ключевое: pf будет автоматически использовать текущий адрес интерфейса, даже если он поменялся после переподключения VPN.
  +
  +
Подключить anchor из pf.conf
  +
  +
/etc/pf.conf (добавьте строки, не ломая apple-якоря):
  +
  +
anchor "nat-utun"
  +
load anchor "nat-utun" from "/etc/pf.anchors/nat-utun"
  +
  +
Включите форвардинг разово (до перезагрузки):
  +
<PRE>
  +
sudo sysctl -w net.inet.ip.forwarding=1
  +
</PRE>
  +
  +
  +
проверка синтаксиса
  +
sudo pfctl -nf /etc/pf.conf
  +
загрузить правила
  +
sudo pfctl -f /etc/pf.conf
  +
sudo pfctl -e # включить pf (если был выключен)
  +
sudo pfctl -sn # посмотреть NAT-правила
  +
sudo pfctl -s state -v | head # посмотреть состояния/NAT
  +
  +
Что с изменениями адреса/интерфейса
  +
  +
Меняется IP на том же utun0 — ничего делать не нужно: -> (utun0) подхватит новый адрес автоматически.
  +
  +
Меняется сам номер интерфейса (utun0 → utun2) — правила с $VPN_IF="utun0" уже не совпадут. Варианты:
  +
  +
Постараться закрепить один и тот же utun в вашем VPN-клиенте (часто получается).
  +
  +
Лёгкий «апдейтер» интерфейса + перезагрузка 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
  +
  +
  +
(Можно оформить это как скрипт «PostUp» вашего VPN-клиента.)
  +
  +
Частые грабли
  +
  +
Забытый () в -> (utun0) — именно тогда NAT «забывает» новый IP.
  +
  +
Нет net.inet.ip.forwarding=1 — клиенты из 192.168.22.0/24 не ходят «наружу».
  +
  +
Неправильно выбран LAN-интерфейс в pass in on … — форвардинг режется фильтром.
  +
  +
MDM/профили могут запрещать менять pf/форвардинг — тогда только через администратора.
  +
  +
Если скажете, какой у вас LAN-интерфейс (en0/en1/bridge0 и т.п.) и кто «вешает» VPN (WireGuard/OpenVPN/встроенный IKEv2), накину точный блок pass in/out и, при желании, минимальный launchd plist для автоприменения.

Версия 12:45, 21 октября 2025


Mac OS NAT V2

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

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

Отдельный файл с 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" load anchor "nat-utun" from "/etc/pf.anchors/nat-utun"

Включите форвардинг разово (до перезагрузки):

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


проверка синтаксиса sudo pfctl -nf /etc/pf.conf загрузить правила sudo pfctl -f /etc/pf.conf sudo pfctl -e # включить pf (если был выключен) sudo pfctl -sn # посмотреть NAT-правила sudo pfctl -s state -v | head # посмотреть состояния/NAT

Что с изменениями адреса/интерфейса

Меняется IP на том же utun0 — ничего делать не нужно: -> (utun0) подхватит новый адрес автоматически.

Меняется сам номер интерфейса (utun0 → utun2) — правила с $VPN_IF="utun0" уже не совпадут. Варианты:

Постараться закрепить один и тот же utun в вашем VPN-клиенте (часто получается).

Лёгкий «апдейтер» интерфейса + перезагрузка 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


(Можно оформить это как скрипт «PostUp» вашего VPN-клиента.)

Частые грабли

Забытый () в -> (utun0) — именно тогда NAT «забывает» новый IP.

Нет net.inet.ip.forwarding=1 — клиенты из 192.168.22.0/24 не ходят «наружу».

Неправильно выбран LAN-интерфейс в pass in on … — форвардинг режется фильтром.

MDM/профили могут запрещать менять pf/форвардинг — тогда только через администратора.

Если скажете, какой у вас LAN-интерфейс (en0/en1/bridge0 и т.п.) и кто «вешает» VPN (WireGuard/OpenVPN/встроенный IKEv2), накину точный блок pass in/out и, при желании, минимальный launchd plist для автоприменения.