Encontrou uma solução. Esta solução deve funcionar para qualquer serviço linux que não possa escutar em interfaces específicas, mas apenas em todos (0.0.0.0) ou um particular, como MySQL, OpenVPN e muitos outros. Então, fazemos com que o serviço ouça um iface e adicione as regras do netfilter / iproute2 para redirecionar todas as solicitações para o mesmo protocolo e porta em outro iface para o nosso serviço no primeiro iface.
A "sessão" (apesar de ser UDP no caso do OpenVPN) é mantida pelo netfilter, e há um módulo conntrack que permite fazer referência a pacotes de uma sessão específica. Neste caso, adicionei uma regra para OUTPUT na tabela mangle para marcar todos os pacotes das sessões DNATed com uma marca. E então eu uso essa marca para rotear os pacotes.
Então, os comandos são:
Defina as variáveis
iface_int2=eth2 # the second internal iface
ip_int2=xx.xx.xx.xx # the IP of the second internal iface
proto=udp # the protocol of the connection
service_port=1194 # the incoming service port
ip_int1=yy.yy.yy.yy # the IP of the first internal iface
ip_gw2=xx.xx.xx.1 # the IP of the default gateway for the second internal iface
Este comando instrui o netfilter a sobrescrever o IP de destino das conexões recebidas em nosso segundo iface.
iptables -t nat -A PREROUTING -i $iface_int2 -d $ip_int2 -p $proto --dport \
$service_port -j DNAT --to $ip_int1
Este comando instrui o netfilter a definir os pacotes de saída (a resposta do serviço) da conexão de entrada sobrescrita (DNATed). --ctorigdst
é o IP de destino original (pré-DNATed) da conexão de entrada
iptables -t mangle -A OUTPUT -p $proto --sport $service_port -m conntrack \
--ctstate DNAT --ctorigdst $ip_int2 -j MARK --set-mark 0x75
Este comando instrui o iproute2 a rotear os pacotes marcados através das definições de rota da tabela 100. Prio é necessário para definir a prioridade mais alta para esta regra, já que é muito específica e não interfere outras regras. Se o prio não for especificado, as regras de roteamento para o primeiro iface interno poderão ter maior prioridade.
ip rule add prio 10 fwmark 0x75 table 100
Este comando adiciona um gateway padrão à tabela 100
ip route add default via $ip_gw2 table 100
Para que tudo isso funcione, é necessário diminuir a aderência do filtro do caminho de retorno no segundo iface interno.
# rp_filter - INTEGER
# 0 - No source validation.
# 1 - Strict mode as defined in RFC3704 Strict Reverse Path
# Each incoming packet is tested against the FIB and if the interface
# is not the best reverse path the packet check will fail.
# By default failed packets are discarded.
# 2 - Loose mode as defined in RFC3704 Loose Reverse Path
# Each incoming packet's source address is also tested against the FIB
# and if the source address is not reachable via any interface
# the packet check will fail.
echo 2 > /proc/sys/net/ipv4/conf/$iface_int2/rp_filter
# -OR-
sysctl -w "net.ipv4.conf.$iface_int2.rp_filter=2"
# -OR-
echo "net.ipv4.conf.$iface_int2.rp_filter=2" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf