Jump to content
Калькуляторы

Как переслать пакет на другой порт? FreeBSD, pf

Мне нужно пакеты 53/udp, приходящие на интерфейс em1, переслать на порт 5353/udp того же интерфейса.

И ответ с порта 5353/udp отправить с порта 53.

И что-то не получается.

Форвардинг выключен (net.inet.ip.forwarding=0), но если его включить, ничего не меняется.

Пробовал такие три варианта:

rdr on em1 proto udp from <net> port 53 -> em1 port 5353

pass in on em1 proto udp from <net> to em1 port 53 rdr-to em1 port 5353

nat on em1 proto udp from <net> to em1 port 53 -> em1 port 5353

Share this post


Link to post
Share on other sites

Через старый добрый 3proxy делается в одну строку. Это ж обычный портмаппинг. Через pf хз, я не знаю, что это. )

Share this post


Link to post
Share on other sites

3proxy не подойдет, мне нужно делать смену порта только для IP-адресов, указанных в <net>.

У меня на сервере работают два сервиса, 53/udp и 5353/udp.

Запросы из <net>, поступающие на 53/udp, нужно перенаправить на 5353/udp.

Ну а всех остальных (не из <net>) нужно не трогать.

Share this post


Link to post
Share on other sites

rdr proto udp from <net> port 53 -> 127.0.0.1 port 5353

pass in on em1 proto udp from <net> to self port 5353

 

Возможно 127.0.0.1 нужно будет заменить на адрес на em1.

 

Через старый добрый 3proxy делается в одну строку. Это ж обычный портмаппинг. Через pf хз, я не знаю, что это. )

PF делает тоже самое только в ядре.

А три таких строчки: http://www.netlab.linkpc.net/forum/index.php?topic=645.0 вообще убивают весь смысл существования подобных программ.

 

-j REDIRECT --to-ports 5353

# -j REDIRECT --to-ports 5353

-j: Command not found.

Exit 1

Share this post


Link to post
Share on other sites

-j REDIRECT --to-ports 5353

Это iptables? У меня pf.

 

Ivan_83, спасибо. А чтобы в обратных пакетах порт с 5353 на 53 менялся, зеркальное правило нужно? Или pf сам сделает?

Share this post


Link to post
Share on other sites

# -j REDIRECT --to-ports 5353

-j: Command not found.

Exit 1

Остряк. На вот ещё остроту:

$ rdr proto udp from <net> port 53 -> 127.0.0.1 port 5353
Python error: <stdin> is a directory, cannot continue

Share this post


Link to post
Share on other sites
А чтобы в обратных пакетах порт с 5353 на 53 менялся, зеркальное правило нужно? Или pf сам сделает?

Ты перенаправляешь пакет в пределах хоста, это не трансляция адреса, а замена/перенаправление.

Сервис получит пакет и ответит на него напрямую юзеру.

Я вроде так делал, самсунговский смарт разницы не увидел.

Ещё я всегда так делаю с 80 портом - перенаправляю на 8080.

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

 

 

Остряк. На вот ещё остроту

Просто не хотелось в очередной раз писать гадости про линукс и что это оффтоипк :)

Он тут меня на днях обломил с ограничениями в splice().

И ещё раз atomic_*() / intrlocked_*() функции мне захотелось, но их там не нашлось, хотя во фре и венде это есть.

Это при том, что я хотел забахать проект который именно суперски-пуперски работает и только под линухом, с бсд лицухой.

И в очередной раз я вспомнил что RCV_LOWAT в линуксе не работает, потому он жрёт проц почём зря, хотя мог бы жрать почти в два раза меньше с тем же результатом.

Share this post


Link to post
Share on other sites

rdr proto udp from <net> port 53 -> 127.0.0.1 port 5353

pass in on em1 proto udp from <net> to self port 5353

Наверное перед port пропущено to?

Проверял запросы с онлайна - почему-то запросы проходят через один.

Возможно нужно порт отправителя в ответах тоже заменять.

Share this post


Link to post
Share on other sites

Возможно нужно порт отправителя в ответах тоже заменять.

Похоже что да. Сделал трансляцию, теперь проходят все запросы.

Ivan_83, просьба проверить, не упустил ли чего?

if_ext = "em1"
if_dns = "xx.yy.124.12"
table <netpub> { xx.yy.124.0/22 aa.bb.104.0/21 }
rdr on $if_ext proto {tcp udp} from !<netpub> to $if_dns port 53 -> $if_dns port 5353
nat on $if_ext proto {tcp udp} from !<netpub> to $if_dns port 53 -> $if_dns port 5353
nat on $if_ext proto {tcp udp} from $if_dns port 5353 to !<netpub> -> $if_dns port 53
...
<нормализация, общие фильтры>
...
pass out quick on $if_ext to any
pass in quick on $if_ext proto {tcp udp} to self port 53
pass in quick on $if_ext proto {tcp udp} from !<netpub> to $if_dns port 5353

Смысл следующий. На сервере работают два DNS-сервера, один кеширующий (на порту 53), другой авторитетный (на порту 5353).

Кеширующий обслуживает запросы только из <netpub>. Авторитетный обслуживает все запросы, но только в своей зоне.

Внешние сети (те, что в <netpub> не входят) должны перенаправляться на авторитетный сервер.

Share this post


Link to post
Share on other sites

Смысл следующий. На сервере работают два DNS-сервера, один кеширующий (на порту 53), другой авторитетный (на порту 5353).

Кеширующий обслуживает запросы только из <netpub>. Авторитетный обслуживает все запросы, но только в своей зоне.

Внешние сети (те, что в <netpub> не входят) должны перенаправляться на авторитетный сервер.

 

Что мешало использовать bind на одном порту?

Pазграничить с помощью ACL пробовали?

Share this post


Link to post
Share on other sites

В каком смысле bind? Если речь о BIND, то я решил попробовать другие реализации. Как работает Unbound мне нравится больше.

А если речь про слушающий сокет, то как я на одном порту запущу два сервиса?

Share this post


Link to post
Share on other sites
Ivan_83, просьба проверить, не упустил ли чего?

Если работает то работает :)

 

В каком смысле bind? Если речь о BIND, то я решил попробовать другие реализации. Как работает Unbound мне нравится больше. А если речь про слушающий сокет, то как я на одном порту запущу два сервиса?

bind() - системный вызов, ассоцирующий сокет с адресом L4 (порт для udp/tcp), делается перед началом приёма трафика.

Можно без фаервола навешать на разные ip на 53 порт разные софтины, для этого в конфиге вместо 0.0.0.0 нужно указывать адрес интерфейса на котором слушать.

Share this post


Link to post
Share on other sites

Ну IP у меня тоже одинаковый.

 

Работает, но не совсем пойму, зачем rdr при nat.

Share this post


Link to post
Share on other sites

Я объясню на примере того что у меня опубликовано.

 

rdr inet proto tcp from any to (self) port $host_port_ext -> $host_addr port $host_port

К нам на порт $host_port_ext пришёл пакет, мы его пересылаем на другой хост $host_addr и порт $host_port.

При пересылке dst ip и dst порт заменяются и пакет ставится в очередь на отправку.

 

nat on $int_if inet proto tcp from any to $host_addr port $host_port -> ($int_if)

Здесь мы перед тем как отправить пакет заменяем в нём src ip и src порт на свои.

src ip берётся с $int_if.

Это делается для того, чтобы хост куда мы пересылаем отвечал нам, при этом nat сделает обратное преобразование и отправит пакет хосту от которого пакет пришёл в rdr правило изначально.

 

nat on $ext_if inet proto tcp from $host_addr port $host_port to any -> ($ext_if)

Тут мы перед отправкой хосту от которого пришёл первый пакет заменяем src ip и порт на свои с $ext_if интерфейса, потому что до попадания в это правило src ip = $host_addr.

Это нужно чтобы получатель знал что пакет к нему пришёл от нас а не от неведомого хоста куда мы на самом деле пересылали пакет.

 

В целом это так.

Возможно в части замены портов в заголовках я где то допустил ошибки, но для IP адресов всё как описано.

Share this post


Link to post
Share on other sites

Ладно, работает - значит не буду трогать.

Просто была мысль, что rdr лишний.

Мне нужен двухсторонний порт-маппинг. Или bi-nat, но для портов, а не IP-адресов.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this