LINUX.ORG.RU

FreeBSD, ipfw, как сделать портфорвардинг с IP адреса VPS на внутренний VPN адрес

 , , , ,


0

2

Буду рад если кто-то сможет помочь, т.к. сам в сетях разбираюсь весьма посредственно.

В общем задача такая что есть VPS, в VPS есть VPN туннель к моей машине, на моей машине веб-сервер, я хочу чтобы из VPS был редирект на мою машину.

Мне удалось в ipwf создать правила допускающие пакеты к 80му порту

#eif - адрес VPS (внешний белый IP)
#cmd = ipfw -q add
$cmd 100 allow log tcp from any to me 80 in via $eif keep-state

Так же добавил и правила для OpenVPN, icmp, ssh, все это работает, OpenVPN соединяется, пинги идут.

А вот портфорвардинг не могу осилить за почти целые сутки чтения статей, форумов, манов.

Для примера раньше на VPS у меня был Линукс, и там эту задачу через iptables я решил за пол-дня (не имея раньше опыта с этой утилитой и знаний про сети)

Было так - крутилась софтинка, которая пинговала адрес который становился доступен когда прикконектится OpenVPN моя машина, и когда адрес пинговался вызывались такие команды:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -d $VPS_ADDR -p tcp --dport 80 -j DNAT --to-destination $MY_PC_IN_NAT
iptables -t nat -A POSTROUTING -d $MY_PC_IN_NAT -p tcp --dport 80 -j SNAT --to-source $VPN_TUNNEL_SERVER_SIDE_ADDR

При том вместо адреса моей машины в моей домашней локальной сети (MY_PC_IN_NAT) можно было, на сколько помню, подставить адрес конца OpenVPN туннеля на мой стороне (VPN_TUNNEL_CLIENT_SIDE_ADDR) и всё работало одинаково хорошо.

Ну соответственно когда пинг пропадал софтинка удаляла эти правила:

sysctl -w net.ipv4.ip_forward=0
iptables -t nat -D PREROUTING
iptables -t nat -D POSTROUTING

Что позволяло реализовать прикольную штуку - когда мой комп выключен VPS на запрос к 80му порту даёт доступ к веб-серверу работающему непосредственно на VPS, а когда мой комп включен - то VPS редиректил доступ к вебсерверу на моём компе.

Вот, буду рад, если кто поможет мне сгенерировать аналогичные iptables команды для ipfw

p.s. курил эти ресурсы, но не помогло

https://dondub.com/2021/04/router-na-freebsd/

https://www.lissyara.su/articles/freebsd/tuning/ipfw_nat/

★★★★★

Последнее исправление: bonta (всего исправлений: 1)

Точно не помню, но вроде так:

В файрволл добавляешь два правила. Первое - обрабатывает все входящие из инета пакеты, которые ты хочешь натить и делает им divert:

ipfw add XXX divert DP1 tcp from any to EXTERNAL_IP LISTEN_PORT in via EXTERNAL_IFNAME

(если ты хочешь чтобы нат не только пробрасывал порты но и раздавал инет в локалку - тут надо ловить не только 80-й порт в и диапазон исходящих портов разрешённый нату)

XXX - номер правила, EXTERNAL_IP LISTEN_PORT - кого редиректим

DP1 - номер divert-сокета (не важно какой но он не должен пересекаться с другими divert-ами)

Второе правило будет ловить все пакеты из спрятанной локалки:

ipfw add YYY divert DP2 ip from any to any in via PRIVATE_IFNAME

Затем делаешь конфиг /etc/natd1.conf

alias_address EXTERNAL_IP
in_port DP1
out_port DP2
log yes
deny_incoming yes
pid_file /var/run/natd1.pid
redirect_port tcp TARGET_IP:TARGET_PORT EXTERNAL_IP:LISTEN_PORT [ALLOWED_CLIENT_IP]
redirect_port можно несколько

EXTERNAL_IP, DP1, DP2 те же что в файрволле

TARGET_IP:TARGET_PORT - куда редиректить

ALLOWED_CLIENT_IP - опционально список разрешённых айпи клиентов этого порта

в rc.conf gateway_enable=«YES»

Можно (но не обязательно) сделать sysctl net.inet.ip.fw.one_pass=0 - тогда пакет после ната будет не сразу отправляться как одобренный, а попадать назад в ipfw на следующее правило (XXX+1 и YYY+1), где его можно дополнительно фильтровать если надо.

Запуск ната так: /sbin/natd -f /etc/nat1.conf

Остановка с помощью kill -9 на его pid.

Можно обернуть в сервис в /usr/local/etc/rc.d/ если надо, но проще (вместе с настройкой ipfw) засунуть в /etc/rc.local

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)

В общем в попытках добиться форваринга сделал конфиг который разрешает всё

ipfw -q -f flush

eif="vtnet0"
cmd="ipfw -q add "

$cmd 105 allow log all from any to any

ipfw -q nat 1 config if $eif reset same_ports \
redirect_port tcp 192.168.0.105:80 80

$cmd 102 nat 1 ip from any to any in via $eif

И что могу сказать - я точно судя по tcp dump вижу что форвариднг работает и запросы на локальной машине появляются как и ответы на vps-е.

Но они приходят в неккоректном виде. Если запустить tcpdump -i ... -n -A port 80 - и сходить в рамках локалки на локальный сайт то там нормальные, осязаемые данные в http протоколе видны, а если из vps через openvpn туннель - то приходят на обоих сторонах (локальная машина и vps) абра-кадабра неструктурированная.

Почему такое не понимаю. Вертится мысль что в ядре создается неверная таблица маршрутизации что не позволяет OpenVPN-у заняться обработкой пришедшего пакета и он не обработанный попадает на внешний сетевой интерфейс, но я слишком не разбираюсь в сетях, маршрутизации, TCP чтобы доверять такой мысли.

Да, я думаю я разберусь, но не ожидал то чтобы настроить редирект портов с OpenVPN понадобится очень много подчерпнуть знаний, для Linux можно было почти ничего не зная, составить конфиг, который работает (правда я вот сейчас смотрю на него и понимаю что тоже не понимю полностью смысла тех правил которые сам же и составил), теперь похоже придется разобраться досканальнее в том как это работает. Это конечно интересно ,да вот жаль что столько труда потратится и потом всеравно забудется, т.к. нужно будет разово.

bonta ★★★★★
() автор топика
Ответ на: комментарий от bonta

С «некорректным видом» я думаю ты что-то напутал.

Запусти tcpdump-ы (только не -A а -X):

1) на компе с веб-сервером для openvpn-интерфейса

2) на впн-сервере для openvpn-интерфейса

3) на впн-сервере для интернет-интерфейса

И сделай http-запрос к 80-му порту впн сервера откуда-нить. Что произойдёт и что в логах всех tcpdump-ов?

firkax ★★★★★
()
Ответ на: комментарий от firkax

В общем да, моё прошлое предположение - какая-то фигня.

На самом деле например если из vps набрать telnet 192.168.0.105 80 то видно что всё работает:

Если посмотреть tcpdump в моей локалке то: на машине .105 по eth0 происходит

02:43:06.844814 IP 192.168.0.105.31940 > 192.168.0.104.80: Flags [S]
02:43:06.845268 IP 192.168.0.104.80 > 192.168.0.105.31940: Flags [S.]
...дальше идёт нормальный TCP обмен

А это уже tcpdump -i tun0 -n -A port 80

01:03:53.050405 IP 10.9.8.1.37555 > 192.168.0.105.80: Flags [S]
01:03:53.051162 IP 192.168.0.105.80 > 10.9.8.1.37555: Flags [S.]
...Дальше идет норм ТСР обмен

10.9.8.1 - адрес VPN туннеля на стороне VPS, а 10.9.8.2 - на стороне 192.168.0.105 - моей домашней машины.

И это пример правильной работы. Дело в том в моей локалке через iptables (по правилам подобным тем что я привёл выше) машина 192.168.0.105 это физическая машина подключенная к роутеру домашнему, а 192.168.0.104 виртуалка, и работало раньше так [VPS]<--vpn-->[192.168.0.105]<--ip_tables_port_forward_to-->[192.168.0.104] - ну и получается сейчас такое работает если из VPS зайти по telnet 192.168.0.105 80

Если же заходить из внешки на VPS то там, согласно tcpdump на моей .105 машине так:

для eth0

02:55:12.813201 IP 192.168.0.105.45128 > 192.168.0.104.80: Flags [S]
02:55:12.813818 IP 192.168.0.104.80 > 192.168.0.105.45128: Flags [S.]
... казалось бы все ок и как в первом слуачае, но нет, вместо дальшнейших шагов TCP (флагов [.] [P.] [.]) будет зацикливание на [S][S.], а все потому что эти пакеты из моей локалки не могут попасть на VPS обратно, поэтому VPS заново шлет запрос на подключение - поэтому и идёт [S][S.] зацикленно

Видно почему не отправляется если смотреть на tun0:

03:00:29.379569 IP 82.200.42.16.40176 > 192.168.0.105.80: Flags [S],
03:00:30.397784 IP 82.200.42.16.40176 > 192.168.0.105.80: Flags [S],
... и так постоянно пока пытается telnet

Т.е. должно быть так:

10.9.8.1.37555 > 192.168.0.105.80

А получается так

82.200.42.16.40176 > 192.168.0.105.80

Т.е. на стороне VPS не работает корректно NAT (в поле SRC IP стоит тот адрес с которого пришел запрос из внешнего интернета, а должен стоять подменённый адрес VPN туннеля со стороны VPS-а)

И получается что в первом случае мой машина знает что пакет пришел с адреса 10.9.8.1 (т.е. vpn туннеля со стороны сервера)

А во втором адрес ответа - это мой временный айпишник от провайдера, по которому я постучался на 80й порт VPS-а

Причём я уже попытался потыкать PF вместо IPFW, составил такой конфиг

# ---------------------Macros section start------------------------------------
WAN_I="vtnet0"
WAN_A="ip vps-a"
# ---------------------Macros section end--------------------------------------

# ---------------------Options secion start------------------------------------
# No restrictions on Loopback Interface.
set skip on lo0
# ---------------------Options secion end--------------------------------------


# Queueing rules section.

# NAT section
#---------------------For cpp-code.ru(local) rules start------------------------
nat on $WAN_I from 10.9.8.2 to any -> ($WAN_I)

rdr pass log on $WAN_I inet proto tcp from any to any port 80 -> 192.168.0.105 port 80
#---------------------For cpp-code.ru(local) rules end--------------------------

# ---------------------Filtering section start----------------------------------

# Deny and log all other incoming/outbound connections.
#block log all

# Allow ping from VPS to all (comment because we allow all outgoing from VPS in rule below).
#pass out inet proto icmp

# Allow all outgoing traffic.
pass out on $WAN_I inet keep state
pass out on tun0 inet keep state

# Allow SSH (simpy).
pass in quick on $WAN_I inet proto tcp to $WAN_A port ПОРТ_SSH keep state

# Allow HTTP connections to internal web server.
pass in on $WAN_I inet proto tcp to $WAN_A port 80 keep state

#---------------------For local pc rules start------------------------
pass in on $WAN_I inet proto udp from any to $WAN_A port ПОРТ_ДЛЯ_VPN
pass in on tun0 inet proto icmp from 10.9.8.2 to 10.9.8.1
pass in on $WAN_I inet proto tcp from any to 192.168.0.105 port 80 keep state
#---------------------For local pc rules end--------------------------

# ---------------------Filtering section end------------------------------------

Но имею ровно такие же проблемы как описал выше - SRC IP для пакетов идущих в tun указан не правильно.

Как думумаете в чём может быть дело? Может быть нужно как-то что-то руками в плане таблицы маршрутизации прописывать? Она кстати такая:

netstat -n -r
Routing tables

Internet:
Destination        Gateway            Flags     Netif Expire
default            xxx.xx.xxx.1       UGS      vtnet0
10.7.0.9           link#2             UHS         lo0
10.7.0.10          link#4             UH         tun1
10.7.0.253         link#2             UHS         lo0
10.7.0.254         link#6             UH         tun2
10.9.8.1           link#2             UHS         lo0
10.9.8.2           link#5             UH         tun0
127.0.0.1          link#2             UH          lo0
192.168.0.101      10.7.0.10          UGHS       tun1
192.168.0.101      10.7.0.254         UGHS       tun2
192.168.0.105      10.9.8.2           UGHS       tun0
xx.xx.xxx.0/20    link#1             U        vtnet0
xxxx.xx.xxx.xx    link#2             UHS         lo0

Там еще есть 2 доп. тун интерфейса к другим моим компам, но я их в файрвол правилах не приводил, т.к. в них нет ничего интересного:

для ipfw
# Allow OpenVPN.
$cmd 400 allow udp from any to me 12345 in via $eif

# Ping
$cmd 389 allow icmp from 10.7.0.10 to 10.7.0.9 in via tun1
$cmd 399 allow icmp from 10.7.0.9 to 10.7.0.10 out via tun1
тоже но для PF
pass in on $WAN_I inet proto udp from any to $WAN_A port 12345
pass in on tun1 inet proto icmp from 10.7.0.10 to 10.7.0.9

В общем другие tun1,tun2 вроде бы не должны никак влиять для неработоспосбности NAT.

Еще догадка - в старых манах пишут что для работы NAT в FreeBSD надо пресобирать ядро, но судя по новым манам и выхолопам в dmesg я пришел к выводу что ядро пересобирать не надо (в выхолопе есть что-то типа nat loadable и в новых манах не говорят про необходимость пересобирать ядро).

При этом я делаю все согласно манов и примеров из статей, короч я уже отчаялся, но не хочется ставить Linux на VPS назад, т.к. во всем остальном FreeBSD мне нравится, кроме того что не могу настроить NAT.

Буду рад накидает кто-нибудь в коком направлении копать дальше.

bonta ★★★★★
() автор топика
Последнее исправление: bonta (всего исправлений: 3)
Ответ на: комментарий от bonta

Какое-то сумбурное изложение, из текста сложно понять где именно запускались дампы. Ты вот пишешь что первый с хоста .105, но там входящие пакеты до .104, и потом выясняется что .104 это вообще виртуалка и дамп ты запускаешь видимо (но я так и не уверен) в ней. Ну да ладно, вроде разобрался.

Т.е. должно быть так:
10.9.8.1.37555 > 192.168.0.105.80

Нет, не должно быть. Всё правильно там стоит настоящий айпи внешнего клиента и никто его не подменяет. Ты порты на бытовом роутере никогда не пробрасывал? Видел же что айпи клиентов там настоящие остаются. Если б роутер их подменял своими - сервер не смог бы вести нормальный учёт айпи-адресов откуда к нему подключаются.

Так что от роутера отстань, пока что никаких проблем с ним не видно. А вот на клиенте настрой роутинг чтобы ответы от твоего веб-сервера (кроме тех что направлены в локалку) слались через tun0 а не в обычный аплинк. Как это делать я не помню (это не обычные таблицы роутинга), но такое точно можно.

Но вообще, режим когда роутер подменяет адрес клиента называется src-nat или masquerade. Можно ли его сделать для входящих коннектов в ipfw/natd я не интересовался никогда.

firkax ★★★★★
()
Ответ на: комментарий от firkax

и дамп ты запускаешь видимо (но я так и не уверен) в ней.

Нет, дампы на .105

В любом случае спасибо. Буду пробовать дальше. Не совсем понял про src-ip, как я на данный момент понимаю теорию он как раз и меняется когда проходит через NAT, и задача NAT-ов менять эти ip-шники таким образом что дойдя до конечной точки конечная точка не узнат IP от кого изначально цепочка была инициирована.

bonta ★★★★★
() автор топика
Ответ на: комментарий от bonta

Если оба дампа на хосте то откуда у хоста на eth0 эти пакеты? Их там вообще не должно быть.

Не совсем понял про src-ip, как я на данный момент понимаю теорию он как раз и меняется когда проходит через NAT, и задача NAT-ов менять эти ip-шники таким образом что дойдя до конечной точки конечная точка не узнат IP от кого изначально цепочка была инициирована.

Это ты описываешь коннекты из локалки наружу. А у входящих - всё наоборот. Так ты пробрасывал когда-нить порты через бытовой роутер?

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

Да, пробрасывал, там всё просто.

В общем я пока приостановил попытки, так и не добившись результата, но буду пробовать ещё.

При том решил пробовать на pf вместо ipfw, как-то он проще, к тому же для моей задачи не нужны такие низкоуровневые фичи которые даёт ipfw (он, как понял, может работать на канальном уровне модели OSI, но а мне такое не надо).

bonta ★★★★★
() автор топика