[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: routing issue (iproute2 and DNAT)



Hello!

On Fri, Jul 20, 2007 at 01:28:36AM -0400, Nicholas wrote:
> 1. iptables
> Предположу что ситуация такая:
> От линка 2 приходят пакеты на tun0(3.3.3.3) и днатятся на 1.1.1.1
> далее ответ от сервера уходит от src 1.1.1.1 (вы же снат не используете).

Да, именно так. Но в итоге, пакет, который уходит наружу имеет src
3.3.3.3, т.к. DNAT отслеживает этот коннекшн и переписывает src 1.1.1.1
на src 3.3.3.3.
Но вот _на каком_ этапе происходит это обратный rewrite src на нужный
нам, я не смог определить. По тому, что я видел, на всех этапах цепочки
iptables src остается 1.1.1.1, но наружу уже уходит с src 3.3.3.3.

Т.е. цепочка такая:

Входящий пакет:
(src:some_where|dst:3.3.3.3) -> DNAT -> (src:some_where|dst:1.1.1.1).

Ответ:
(src:1.1.1.1|dst:some_where) -> (DNAT engine that rewrites src) -> (src:3.3.3.3|dst:some_where)

Т.е. DNAT сам отслеживает коннекшн и корректно возвращает нужный
src-пакету. 
Но! Этот механизм срабатывает уже _после_ routing decision. Т.е. сначала
принимается решение о том, что пакет нужно смаршрутизировать по дефолту
(т.к. видно что src:1.1.1.1), а потом уже переписывается на src:3.3.3.3.

И, повторюсь, похоже что по iptables пакет проходит с src:1.1.1.1. По
крайней мере я хотел отловить пакет с src:3.3.3.3 на всех этапах
iptables, но нигде не было попаданий. Но "наружу" пакет уходит с
src:3.3.3.3 это точно.

> 
> Я бы попробовал добавить снат:
> -t nat -A POSTROUTING -p tcp -d "линк 2" -j SNAT ... 3.3.3.3

Т.е. для входящих пакетов src переписывать на src-интерфейса? Нельзя, приложений должно видеть src-ip
клиентского софта, который к нему обращается.

> 2. route
>  32765:  from 3.3.3.3 lookup tun0_net
> 
> Возможно вместо 3.3.3.3 стоит использовать ip линка 2 ?
> http://gazette.linux.ru.net/rus/articles/lartc/c322.html
> "4.1. Простая маршрутизация по источнику."

Возможно мы немного запутались, 3.3.3.3 и есть ip линка 2.

Еще раз обрисую схему:

(eth0:2.2.2.2)->\
                 -> DNAT (lo:1.1.1.1)
(tun0:3.3.3.3)->/

1. Если пакет заходит через eth0, то его dst переписывается на 1.1.1.1,
ответ от приложения уходит с (src:1.1.1.1, dst:client_ip). Этот пакет
попадает в DNAT, DNAT распознает в нем уже начатую сессию и переписывает
его на (src:2.2.2.2|dst:client_ip).

2. Если пакет заходит через tun0, происходит тоже самое, только DNAT
переписывает его src на адрес tun0, т.е. 3.3.3.3

Все хорошо, так и должно работать. Но, принятие решения о том, куда
нужно маршрутизировать пакет происходит _до_ того, как DNAT перепишет
src исходящего с сервера пакета на правильный.
Т.е. механизм раутинга всегда рассматривает ситуацию так, вроде src у
пакета 1.1.1.1, а значит он должен уйти в eth0.

В итоге имеем то, что в eth0 уходят ответы с src:2.2.2.2 и src:3.3.3.3
(сначала принято решение о раутинге, потом DNAT вернул правильный src).

Задача состоит в том, чтобы как-то вклиниться _после_ того, как DNAT
переписал src-ip (чтобы понять, куда его нужно раутить по-настоящему) и
либо как-то перезапустить процесс раутинга, либо переписать его через -j
ROUTE.
Но вот этой самой точки, когда DNAT "вернул" src-адрес я в цепочке
iptables отследить не смог.


=== solution ===

В общем, я сделал следующим образом:

-t nat -A PREROUTING -p tcp -d 3.3.3.3 --dport 80 -j DNAT --to-destination 1.1.1.1:80
-t mangle -A PREROUTING -i tun0 -m state --state NEW -j CONNMARK --set-mark 1
-t mangle -A OUTPUT -j CONNMARK --restore-mark

Ну и:

32761:  from all fwmark 0x1 lookup tun0_net

таким образом все работает корректно. Да, и еще нужно отключить
rp_filter.


> 3.
> И еще совет - удобно сделать iptables-save > iptables_v1 и редактировать 
> файл, а потом делать iptables-restore iptables_v2

Спасибо.

-- 
WBR,
Alexander Burnos



Reply to: