iptables - Alvo para rotear o pacote para uma interface específica?

22

Meu servidor doméstico tem duas interfaces principais, eth1 (uma conexão padrão com a Internet) e tun0 (um túnel OpenVPN). Eu gostaria de usar iptables para forçar todos os pacotes gerados por um processo local pertencente ao UID 1002 a sair através de tun0 , e todos os outros pacotes para sair através de eth1 .

Eu posso marcar facilmente os pacotes correspondentes:

iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11

Agora, gostaria de colocar alguma regra na cadeia POSTROUTING (provavelmente da tabela mangle) para corresponder aos pacotes marcados com 11 e enviá-los para tun0 , seguido por uma regra que corresponda a todos os pacotes e enviá-los para eth1 .

Eu encontrei o alvo ROUTE, mas isso parece apenas reescrever a interface de origem (a menos que eu esteja lendo incorretamente).

iptables é capaz disso? Tenho que mexer com a tabela de roteamento (via ip route ou apenas os comandos legados route )?

Edit: Eu pensei que talvez eu devesse fornecer mais informações. Eu não tenho outras regras iptables no momento (embora eu possa criar algumas regras para realizar tarefas não relacionadas no futuro). Além disso, a saída de ip route é:

default via 192.168.1.254 dev eth1  metric 203
10.32.0.49 dev tun0  proto kernel  scope link  src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.73  metric 203

Eu não toquei na tabela de roteamento - isso é exatamente como está no momento (embora pareça bastante sujo). Desculpe, mas não tenho o comando legado route instalado nesta máquina.

E a saída de ip addr (é claro, eth0 e eth2 podem ser ignoradas - eles são NICs que não estão sendo usados no momento):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast     state UP qlen 1000
    link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1
    inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc     pfifo_fast state UNKNOWN qlen 100
    link/none
    inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0

Edit: Eu tenho algo sorta funcionando, mas não está encaminhando pacotes marcados para tun0. Basicamente, eu adicionei uma tabela (11) e usei:

ip route add table 11 via 10.32.0.49 dev tun0
ip rule add priority 10000 fwmark 11 table 11

Quando eu só sudo -u user1000 wget -qO- whatismyip.org , obtenho o endereço IP externo da minha casa, mas se eu faço sudo -u user1002 wget -qO- whatismyip.org , também recebo o endereço IP da minha casa (mas eu deveria obter o IP na outra extremidade do túnel OpenVPN) .

A execução de iptables -vL confirma que os pacotes estão sendo correspondidos pela regra de marcação, mas não parecem estar seguindo a regra de roteamento.

EDIT: Eu passei muito tempo nisto e, embora ainda não funcione, acho que estou um pouco mais perto.

A regra iptables deve estar na cadeia OUTPUT da tabela mangle . Acho que também preciso de uma regra de MASQUERADE na cadeia POSTROUTING da tabela nat , para definir o endereço de origem. Entretanto, o reencaminhamento que ocorre após o mangle do OUTPUT não está funcionando corretamente.

Eu passei 5 horas nisto agora, então estou dando um tempo e provavelmente voltarei a ele mais tarde hoje à noite ou amanhã.

    
por Ethan 29.12.2011 / 19:56

4 respostas

5

Eu resolvi isso. O problema era com as regras de roteamento na tabela 11. A Tabela 11 foi sendo atingida, mas as regras de roteamento a tornam inoperante. Este script é o que eu uso agora, e parece funcionar bem (embora seja obviamente específico para minha configuração). Além disso, criei uma nova tabela 21 dedicada ao uplink principal (eth1).

# Add relevant iptables entries.
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

# Flush ALL THE THINGS.
ip route flush table main
ip route flush table 11
ip route flush table 21
ip rule flush

# Restore the basic rules and add our own.
ip rule add lookup default priority 32767
ip rule add lookup main priority 32766
ip rule add fwmark 11 priority 1000 table 11
# This next rule basically sends all other traffic down eth1.
ip rule add priority 2000 table 21

# Restore the main table.  I flushed it because OpenVPN does weird things to it.
ip route add 127.0.0.0/8 via 127.0.0.1 dev lo
ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73
ip route add default via 192.168.1.254

# Set up table 21.  This sends all traffic to eth1.
ip route add 192.168.1.0/24 dev eth1 table 21
ip route add default via 192.168.1.254 dev eth1 table 21

# Set up table 11.  I honestly don't know why 'default' won't work, or
# why the second line here is needed.  But it works this way.
ip route add 10.32.0.49/32 dev tun0 table 11
ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11
ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11

ip route flush cache

## MeanderingCode edit (because I can't comment, yet)

Thanks for this answer! It seems as though this could get messy, as you would have to maintain route info here (possibly duplicating, or breaking other things which may want to set routes.

You may be experiencing "weird things" in your routing table from OpenVPN because the server is configured to "push" routes, enabling all traffic to route through the VPN network interface, rather than the "bare" internet. Or your OpenVPN config or whatever script/application sets it up is setting routes.

In the former case, you can edit your OpenVPN configuration and put in a line containing "route-nopull"
In the latter, check configuration for OpenVPN or any wrapper (network-manager-openvpn, for example on many current linux desktop distros)
In either case, eliminating the routing configuration where it's getting set is cleaner and safer than flushing the table, depending on when you run this script and what else your system is doing.

Cheers!

    
por 30.12.2011 / 05:02
22

Recentemente, encontrei um problema semelhante, embora um pouco diferente. Eu queria rotear somente a porta TCP 25 (SMTP) em uma interface tap0 do OpenVPN, enquanto roteava todo o outro tráfego (mesmo para o mesmo host) sobre a interface padrão.

Para fazer isso, eu tive que marcar pacotes e configurar regras para lidar com isso. Primeiro, adicione uma regra que torne os pacotes de rota do kernel marcados com 2 através da tabela 3 (explicado posteriormente):

ip rule add fwmark 2 table 3

Você poderia ter adicionado um nome simbólico a /etc/iproute2/rt_tables , mas eu não me preocupei em fazer isso. O número 2 e 3 são escolhidos aleatoriamente. Na verdade, estes podem ser os mesmos, mas para maior clareza eu não fiz isso neste exemplo (embora eu faça isso em minha própria configuração).

Adicione uma rota para redirecionar o tráfego em uma interface diferente, supondo que o gateway seja 10.0.0.1 :

ip route add default via 10.0.0.1 table 3

Muito importante! Lave seu cache de roteamento, caso contrário você não receberá uma resposta e ficará sentado com as mãos no cabelo por algumas horas:

ip route flush cache

Agora, defina uma regra de firewall para marcar os pacotes designados:

iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2

A regra acima se aplica somente se os pacotes vierem da máquina local. Veja o link . Ajuste-o às suas necessidades. Por exemplo, se você quiser apenas rotear o tráfego HTTP de saída pela interface tap0 , altere 465 para 80.

Para evitar que os pacotes enviados por tap0 obtenham seu endereço de LAN como IP de origem, use a regra a seguir para alterá-lo para seu endereço de interface (assumindo 10.0.0.2 como endereço IP da interface tap0 ):

iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.2

Finalmente, relaxe a validação da origem do caminho inverso. Alguns sugerem que você defina como 0 , mas 2 parece ser a melhor opção de acordo com o link . Se você ignorar isso, receberá pacotes (isso pode ser confirmado usando tcpdump -i tap0 -n ), mas os pacotes não serão aceitos. O comando para alterar a configuração para que os pacotes sejam aceitos:

sysctl -w net.ipv4.conf.tap0.rp_filter=2
    
por 14.05.2012 / 21:52
2

Eu acho que você quer:

/sbin/ip route add default via 10.32.0.49 dev tun0 table 11
/sbin/ip rule add priority 10000 fwmark 11 table 11

link

Mas eu não testei o acima.

    
por 29.12.2011 / 22:02
0

Isto pode ser feito sem o comando iptables Execute simple ip command

Para o uid 1002:

ip rule add uidrange 1002-1002 table 502

Adicione a rota padrão para a tabela 502 na interface que você deseja dizer

eth0 ip rule add default via a.b.c.d dev eth0
    
por 30.12.2015 / 15:14