iptables --set-mark-通过不同的接口路由不同的端口


15

简而言之,
三个接口:eth0(LAN),eth1(ADSL)和eth2(4G)。
eth0-> eth1:有效
(端口80、443、4070)eth0-> eth2:不会发生


这是该想法的图形表示:

通过eth2的端口80和443,
通过eth1的其余端口
在此处输入图片说明

网络方案:

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 






我认为,这个新脚本会将22和4070重新路由到适当的表。
但是,到达该表后,它不会重新路由到eth2。




该脚本有效,除了22和4070!

(端口80未注释,并且可以通过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 -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









旧脚本:


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




我创建了一个router.sh脚本来设置环境,以防万一。我有3个端口要发送到4G连接,其余的要通过陆线ADSL连接发送。为此,我已指示iptables处理默认路由上的软件包,并在--dport == 443 | 80 | 4070

但是,这行不通;无论如何,我仍会通过座机路由。

这是我的脚本的样子:

#!/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

我还尝试将这3个添加到脚本的bottomg中:

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"

也尝试没有成功:

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

最后但并非最不重要的,尝试过:

## 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

路由有效,我可以浏览网络,听音乐而不是,但是我通过错误的界面进行操作。我已经在Google上搜索了很长时间,并且发现了点点滴滴,以了解我在做什么以及为什么这么做。我可以通过tc进行流量整形,但如果可以通过在iptables中标记包来实现,那将对我有很大帮助。

我的猜测是,我在不同的规则上犯了错误的命令,主要是假冒伪劣部分?还是应该在那里?

有人可以解释从外部接口(一个或两个协议)到内部10.0.0.0地址空间的DNAT端口怎么说tcp:80吗?



输出:

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

遵循以下指示信息:
在不同接口上进行基于目标por的输出流量通信
iptables-forward-specific-port-to-specific-nic
在一些其他相关线程中。


抱歉,有没有理由只将apache绑定到接口localhost的地址和eth2
Jan Marek

@JanMarek:这里没有提到Apache。并且为您提供信息,在ethX的ip地址上绑定套接字将防止ethX局域网中的主机使用ethY的ip地址访问本地服务器,也不会阻止主机ethY使用ethX的ip地址访问服务器。请记住,Linux使用弱主机模型。
BatchyX

好的,可能会有更多的Web服务器,而不仅仅是apache服务器...不过,在eth2接口上绑定Web服务器可能是一个简单的解决方案。但是我知道我可能是错的。
Jan Marek

Answers:


6

BatchyX已经对iptables和路由给出了很好的解释,因此我将练习惰性并直接使用脚本。

它应该通过192.168.0.91将所有流量NAT到端口80,443,22,4070。其余所有将通过192.168.1.254进行NAT。

我重新进行测试,最后按照本指南进行操作。该指南中缺少的是我脚本的最后3行。我是从另一个端口上找到的,但是却找不到该链接。

这是一个经过测试的工作脚本。

需要默认路线

我未在脚本中添加的一件事是设置默认路由。它应该是

route add default gw 192.168.1.254

这样做时route -n,它应该是唯一的默认路由(目的地:0.0.0.0)

0.0.0.0    192.168.1.254    0.0.0.0    UG    0    0    0    eth1

固件路由器

#重置/刷新iptables
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P输入接受
iptables -P接受
iptables -P输出接受

#重置/刷新/设置IP路由(表4)
ip路由刷新表4
ip route show table主| grep -Ev ^默认| 同时阅读ROUTE; ip route add table 4 $ ROUTE; 做完了
IP路由添加表4默认通过192.168.0.1

#标记具有匹配D.Port的数据包
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

#SNAT规则
iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 192.168.1.74
iptables -t nat -A POSTROUTING -o eth2 -j SNAT --to-source 192.168.0.91

#IP路线
ip规则添加fwmark 4表4
ip路由刷新缓存

#IP堆栈
#这是指南中缺少的部分
回声1> / proc / sys / net / ipv4 / ip_forward
对于/ proc / sys / net / ipv4 / conf / * / rp_filter中的f; 做echo 0> $ f; 做完了
回声0> / proc / sys / net / ipv4 / route / flush

PS1:简而言之,MASQUERADE对于具有多个外部IP且需要某种负载平衡或需要DNAT来处理传入流量的NAT的NAT(在大多数情况下,当然对于您而言,这当然不起作用)。您需要SNAT方向控制。

PS2:仅 iptables是不够的。


首先,为直接进入脚本而欢呼:)我将在今晚尝试此操作,因为我回到运行该脚本的环境中!
2012年

嗯,可能需要大量修改。让我知道结果。
约翰兆

修改后,现在应该可以工作。
约翰兆


我爱你,好头痛,您解决了!谢谢!
2012年

6

注意:我只考虑了第一个脚本,而忽略了旧的脚本。

  • 您不需要使用当前的iptables手动修改proprobe netfilter模块。这仅对于自定义连接跟踪器是必需的。
  • 不要混淆routeip route。这是纯粹的邪恶。只需使用ip无处不在,忘了ifconfigroute
  • /etc/iproute2/rt_tables在重启后不会重置。一遍又一遍地添加相同的条目不是一个好主意,您只需要执行一次即可。请记住,rt_tables只需将名称别名定义为数字值,就不会更改任何配置。

  • 现在开始iptables:在您的FORWARD链中,您将来自LAN的数据包丢弃到4G。这是不好的。该FORWARD挂钩路由完成后使用。至此,所有策略路由均已完成,并且已经知道该数据包应发送到4G还是ADSL。在路由之内FORWARD或之后都不会进行重新路由FORWARD(从技术上讲,重路由可以POSTROUTING在严重的情况下进行,但要回到原点)。

现在开始路由:请记住,Ubuntu默认启用了反向路径过滤。反向路径过滤的工作原理如下:当内核从接口A接收到一个数据包(可以转发还是不转发)时,它将转换源地址和目标地址,并检查是否应通过接口A路由生成的数据包。如果不是,数据包将作为地址欺骗尝试被丢弃。

对于从接收的数据包eth0,这不是问题。对于从接收到的数据包eth1,这也不成问题,因为当反转源IP地址和目标IP地址时,内核将使用table中的默认路由main。对于eth2不标记的从接收到的数据包,这是一个问题,因为内核将命中表中的默认路由main,并认为这些数据包应已从接收到eth1。最简单的解决方案是在eth1上禁用反向路径过滤:

sysctl -w net.ipv4.conf.eth1.rp_filter=0

所有很棒的评论,是的,我这方面存在一些错误的逻辑,例如每次都附加到rt_tables上,尤其是没有像我应该的那样清除某些表,但是我会到达的:)我会尝试一切如果有效,则为您+50,最重要的是,您已免于被割断成片而陷入困境!:)
2012年

1
下面的脚本有效,但是您也应该感谢您,先生,我给了我一两件事,rp_filter = 0帮了大忙!:D
2012年

@BatchyX非常有用,也可以投票给您。
约翰兆

@Torxed我看到提到所有接口的rp_filter的帖子都需要禁用。我不确定它是否可以以其他方式工作。
John Siu

@JohnSiu:您只需要在有问题的接口上禁用rp过滤器。在这种情况下,它是eth1,因为在未设置标记的情况下没有通往该接口的路由。eth2没有这种问题,因为默认路由进入该接口。对于eth0,实际上保持启用rp过滤器很有用,否则,LAN上的某人可以伪造一个IP数据包,该IP数据包的源地址位于Internet上,而目标地址位于LAN上,并且路由器会很乐意接受并转发它回到... eth0。
BatchyX
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.