iptables --set-mark - Rotear portas diferentes através de interfaces diferentes

13

Conto curto,
3 interfaces, eth0 (LAN), eth1 (ADSL), eth2 (4G).
eth0 -> eth1: Funciona
(portas 80, 443, 4070) eth0 -> eth2: não acontece


Esta é uma representação gráfica da ideia:

Portas 80 e 443 via eth2
e o restante via eth1
insira a descrição da imagem aqui

Netscheme:

eth0: -ip 10.0.0.1 -net 10.0.0.0/8 -gw 10.0.0.1 (the servers own intf) 
eth1: -ip 192.168.1.74 -net 192.168.1.0/24 -gw 192.168.1.254 
eth2: -ip 192.168.1.91 -net 192.168.0.0/24 -gw 192.168.0.1 






Esse novo script redireciona 22 e 4070 para a tabela apropriada, eu acho.
No entanto, depois de chegar a essa tabela, ela não é redirecionada para eth2.




Este script funciona, exceto para 22 e 4070!

(A porta 80 não possui comentários e funciona, mas via eth1, o que está errado.)

modprobe iptable_nat
modprobe ip_conntrack

echo "1" > /proc/sys/net/ipv4/ip_forward

iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -F PREROUTING
iptables -t nat -F
iptables -t mangle -F
iptables -F
# This next line restores any issues trying to connect to something
# if you get weird ACK packets when trying to connect (at least i did)!
iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark
ip route flush table main

iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 22 -j MARK --set-mark 1
###  iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 -j MARK --set-mark 1
iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 4070 -j MARK --set-mark 1

## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
## -- Does the same as ip route below? route add default gw 192.168.1.254


echo "201 eth2.out" >> /etc/iproute2/rt_tables

ip rule add fwmark 1 table eth2.out
ip route add default via 192.168.0.1 dev eth2 table eth2.out
ip route add default via 192.168.1.254 dev eth1



## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE









Script antigo:


  Ignore everything below unless you're interested in retracing my steps!!




Eu criei um script router.sh para configurar meu ambiente, caso eu faça algo ruim. Eu tenho três portas que eu quero enviar para uma conexão 4G e o restante através de uma conexão ADSL fixa. Para fazer isso, eu instruí o iptables a manipular pacotes na rota padrão e enviá-los através da minha interface 4G se o --dport == 443 | 80 4070

No entanto, isso não funciona; Eu ainda estou sendo roteado pelo meu telefone fixo, não importa o quê.

É assim que meu script se parece:

#!/bin/bash

## routing tables
# wireless = 4G via eth2
# adsl = adsl via eth1

modprobe iptable_nat
modprobe ip_conntrack

echo "1" > /proc/sys/net/ipv4/ip_forward

iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -t nat -F
ip route flush table main
ip route flush table wireless
ip route flush table adsl

## Setup routing tables
# ADSL
ip route add table adsl to 192.168.1.0/24 dev eth1
# 4G
ip route add table wireless to 192.168.0.0 dev eth2
ip rule add fwmark 0x1 table wireless

## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
route add default gw 192.168.1.254


## Forward ports into the LAN
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.0.3:80


## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1

## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -A FORWARD -j LOG
#iptables --table nat --append POSTROUTING --out-interface eth2 --jump SNAT --to-source "192.168.1.74"
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

Eu também tentei adicionar esses 3 ao bottomg do script:

iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 80 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 443 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 4070 -j SNAT --to "192.168.0.91"

Também tentei sem sucesso:

iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 1

Por último, mas não menos importante, tentei:

## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1

O roteamento funciona, eu posso navegar na web, ouvir música e tudo o mais, mas estou fazendo isso através da interface errada. Pesquisei no Google por um longo tempo e encontrei fragmentos para entender o que estou fazendo e por que estou fazendo. Eu poderia fazer modelagem de tráfego via tc, mas se for possível através da marcação de pacotes no iptables, isso me ajudaria bastante.

Meu palpite é que estou fazendo o pedido errado nas diferentes regras, principalmente a parte MASQUERADE ? ou se isso deveria estar lá?

Alguém pode explicar como a porta DNAT diz, tcp: 80 de uma interface externa (um ou ambos os protocolos) para um espaço de endereço 10.0.0.0 interno?



Saídas:

root@Netbridge:~# route -n Kernel IP routing table Destination    

Gateway         Genmask         Flags Metric Ref    Use Iface<br>
0.0.0.0         192.168.1.254   0.0.0.0         UG    0      0        0 eth1<br>
10.0.0.0        0.0.0.0         255.0.0.0       U     0      0        0 eth0<br>
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 eth2<br>
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1


root@Netbridge:~# ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0c:29:7e:9e:4e  
          inet addr:10.0.0.1  Bcast:10.255.255.255  Mask:255.0.0.0

eth1      Link encap:Ethernet  HWaddr 00:0c:29:7e:9e:58  
          inet addr:192.168.1.74  Bcast:192.168.1.255  Mask:255.255.255.0

eth2      Link encap:Ethernet  HWaddr 00:0c:29:7e:9e:62  
          inet addr:192.168.0.91  Bcast:192.168.0.255  Mask:255.255.255.0

Siga estas instruções:
output-traffic-on-different-interfaces-based-on-destination-por
iptables-forward-specific-port-to-specific-nic
Entre alguns outros threads relacionados.

Torxed
fonte
Sinto muito, mas existe um motivo para não vincular o apache apenas ao localhoste ao endereço da eth2interface?
Jan Marek
@JanMarek: Não há menção ao apache aqui. E, para sua informação, a ligação de um soquete ao ethXendereço IP de um servidor impedirá que os hosts na ethXLAN acessem o servidor local usando ethYo endereço IP, e não impedirá que os hosts ethYacessem o servidor usando ethXo endereço IP. Lembre-se de que o Linux usa um modelo de host fraco.
BatchyX
OK, é possível haver mais servidores da Web, não apenas o servidor apache ... Mas eu, que vinculo o servidor da Web na interface eth2, pode ser uma solução simples. Mas eu posso estar errado, eu sei.
Jan Marek

Respostas:

4

O BatchyX já dá uma explicação muito boa sobre iptables e roteamento, então exercitarei minha preguiça e irei diretamente para o script.

Deve NAT todo o tráfego para a porta 80.443,22.4070 através de 192.168.0.91. Todo o resto será NAT através de 192.168.1.254.

Eu refiz meus testes e acabo seguindo este guia . O que está faltando nesse guia são as três últimas linhas do meu script. Que descobri de outra porta, mas perdi o controle desse link.

É um script de trabalho testado.

Precisa de rota padrão

Uma coisa que eu não coloquei no script é configurar a rota padrão. Deveria ser

route add default gw 192.168.1.254

Ao fazê- route -nlo, deve ser a única rota padrão (Dest: 0.0.0.0)

0.0.0.0    192.168.1.254    0.0.0.0    UG    0    0    0    eth1

fw-router.sh

# Redefinir / liberar iptables
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

# Redefinir / liberar / configurar rota IP (tabela 4)
tabela de nivelamento de rota ip 4
tabela ip show table main | grep -Ev ^ padrão | enquanto lê ROUTE; rota ip adicionar tabela 4 $ ROUTE; feito
rota ip adicionar tabela 4 padrão via 192.168.0.1

#Mark Packet com D.Port correspondente
iptables -t mangle -A PREROUTING -p tcp --dport 22 -s 10.0.0.0/24 -j MARK --set-mark 4
iptables -t mangle -A PREROUTING -p tcp --dport 80 -s 10.0.0.0/24 -j MARK --set-mark 4
iptables -t mangle -A PREROUTING -p tcp --dport 443 -s 10.0.0.0/24 -j MARK --set-mark 4
iptables -t mangle -A PREROUTING -p tcp --dport 4070 -s 10.0.0.0/24 -j MARK --set-mark 4

Regras do #SNAT
iptables -t nat -A POSTROUTING -o eth1 -j SNAT - para fonte 192.168.1.74
iptables -t nat -A POSTROUTING -o eth2 -j SNAT - para fonte 192.168.0.91

#IP Route
regra ip adicionar fwmark 4 tabela 4
cache de liberação de rota ip

#IP Stack
#Esta é a parte que falta no guia
eco 1> / proc / sys / net / ipv4 / ip_forward
para f em / proc / sys / net / ipv4 / conf / * / rp_filter; faça eco 0> $ f; feito
eco 0> / proc / sys / net / ipv4 / route / flush

PS1: Em resumo, MASQUERADEnão funciona (na maioria dos casos, e definitivamente no seu caso) para NAT com vários IPs externos que precisam de algum tipo de balanceamento de carga ou precisam de DNAT para lidar com o tráfego recebido. Você precisa SNATde controle de direção.

PS2: o iptables puro não é suficiente.

John Siu
fonte
Antes de mais nada, aplausos por ir diretamente ao script :) Vou tentar isso hoje à noite quando voltar ao ambiente em que isso será executado!
Torxed
hmm, pode precisar de uma revisão pesada. Deixe-me saber o resultado.
John Siu
Revisado, deve estar funcionando agora.
John Siu
Doce, responderemos em breve: D
Torxed
Eu te amo, muita dor de cabeça e você resolveu! Obrigado!
Torxed
5

Nota: Apenas considerei o primeiro script, ignorando o antigo.

  • Você não precisa modificar os módulos do netfilter manualmente com as tabelas de ip atuais. Isso é necessário apenas para rastreadores de conexão personalizados.
  • Não misture routee ip route. Isso é puro mal. Basta usar em ipqualquer lugar e esquecer ifconfigeroute
  • /etc/iproute2/rt_tablesnão é redefinido nas reinicializações. Anexar a mesma entrada repetidamente não é uma boa ideia, você só precisa fazer uma vez. Lembre-se de que rt_tablesapenas define aliases de nome para valores numéricos, isso não altera nenhuma configuração.

  • Agora iptables: em sua FORWARDcadeia, você descarta pacotes provenientes da LAN para 4G. Isto é mau. o FORWARDgancho é usado após a conclusão do roteamento. Nesse ponto, todo o roteamento de diretiva está concluído e já se sabe se o pacote deve ser enviado para 4G ou ADSL. Não há redirecionamento realizado em FORWARDou após FORWARD(bem, tecnicamente, o redirecionamento pode ser realizado POSTROUTINGem casos graves, mas voltando ao ponto).

Agora para o seu roteamento: lembre-se de que o Ubuntu habilita a filtragem de caminho reverso por padrão. A filtragem de caminho reverso funciona da seguinte maneira: Quando o kernel recebe um pacote (seja ele encaminhado ou não) de uma interface A, ele inverte o endereço de origem e o endereço de destino e verifica se o pacote resultante deve ser roteado pela interface A. Caso contrário, o pacote será descartado como uma tentativa de falsificação de endereço.

Para pacotes recebidos de eth0, isso não é um problema. Para pacotes recebidos de eth1, isso também não é um problema, porque ao reverter o endereço IP de origem e o endereço IP de destino, o kernel será a rota padrão na tabela main. Para pacotes recebidos de eth2, que você não marca, isso é um problema, porque o kernel atingirá a rota padrão na tabela maine considere que esses pacotes deveriam ter sido recebidos de eth1. A solução mais fácil é desativar a filtragem de caminho reverso no eth1:

sysctl -w net.ipv4.conf.eth1.rp_filter=0
BatchyX
fonte
Todos os ótimos comentários e sim, há alguma lógica defeituosa da minha parte, por exemplo, anexando a rt_tables a cada vez e, especialmente, não limpando certas tabelas, assim como eu deveria, mas chegarei lá :) Vou tentar tudo :) se funcionar, em caso positivo, +50 para você e, mais importante, você salvou um homem atrás de ser picado em pedaços! :)
Torxed
O script abaixo funciona, mas você merece toda a gratidão, você me deu uma coisa ou duas para pensar e rp_filter = 0 ajudou muito! : D
Torxed
@BatchyX muito informativo, voto positivo para você também.
precisa
@ Torxed O post que eu vi mencionar rp_filter para ALL interface precisa ser desativado. Não tenho certeza se funciona de outra maneira.
precisa
@ JohnSiu: Você só precisa desativar o filtro rp nas interfaces em que é problemático. Nesse caso, é eth1, porque não há rota para essa interface quando as marcas não estão definidas. O eth2 não tem esse problema, pois a rota padrão entra nessa interface. Para eth0, é realmente útil manter o filtro rp ativado, caso contrário, alguém na LAN pode forjar um pacote IP com um endereço de origem na Internet e um endereço de destino na LAN, e o roteador aceitaria com prazer e encaminharia de volta para ... eth0.
BatchyX