mangle表的主要功能是根據規則修改數據包的一些標志位,以便其他規則或程序可以利用這種標志對數據包進行過濾或策略路由。
使用策略路由
對應的場景, 都是有多個網口, 常見的使用步驟
1. 創建路由表 Create new routing table
編輯 /etc/iproute2/rt_tables
, 添加
[ID of your Table] [Name of your table]
使用ip rule 對指定的路由表table [Table Name or Table ID]
添加路由規則.
使用下面的命令檢查
ip route show table [Table Name or Table ID]
為路由表指定默認的路由設備
ip route add default dev "${TUNDEV}" src "${INTERNAL_IP4_ADDRESS}" table "${TABLENAME}"
# 在路由表100上添加一個默認路由(對所有地址), 使用本地網關192.168.1.1, 這是一個可以從eth0到達的地址
ip route add default via 192.168.1.1 dev eth0 table 100
# 對10.1.1.0/30這個目的地址范圍添加路由規則, 並添加MPLS標簽
ip route add 10.1.1.0/30 encap mpls 200/300 via 10.1.1.1 dev eth0
確定數據包走哪個路由表
默認每個數據報文走的路由表都是main, 你可以給滿足一定規則的數據報文指定不同的路由表, 而未滿足的還繼續使用默認的路由表.
路由規則(ip rule)
這里有所有可能用到的參數列表, 如果還不夠, 你可以使用fwmark. 給數據報文打fwmark標簽可以通過iptables來處理, 然后通過ip rule來處理. 例如
# 來源於167.99.208.1的用指定table
ip rule add from 167.99.208.1 table [table-name]
# 所有來源都用table ztable1
ip rule add from all table ztable1
# 所有來源中帶標簽2的都用table 20
ip rule add from all fwmark 2 table 20
2. 使用iptables打標簽
使用的格式為 -j MARK --set-mark <Your marknumber in decimal form>
. MARK這個target只在mangle中有效.
對於流入的數據報文可以使用-t mangle -A PREROUTING
, 對於流出的數據報文可以使用-t mangle -A OUTPUT
. 注意: 當數據報文被進程(例如apache)處理過之后, 標簽就丟失了. 所以如果打過標簽的報文在返回時不正確, 只給流入的報文打標簽是不夠的, 你必須給產生的流出報文也打上標簽.
3. 遇到的問題
報文丟失
很可能是因為被認為"martian"而被丟棄了. 在kernel中被丟棄可能不會留下日志, 可以通過下面的方式開啟日志
# 編輯 /etc/sysctl.conf
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.log_martians = 1
如果確認是被作為martian丟棄, 可以進行下面的修改
# 編輯 /etc/sysctl.conf
# Enables source route verification
net.ipv4.conf.default.rp_filter=0
# Enable reverse path
net.ipv4.conf.all.rp_filter=0
關於 fwmark
https://docs.huihoo.com/hpc-cluster/linux-virtual-server/HOWTO/LVS-HOWTO.fwmark.html
Karl Kopper (Apr 2004) said that he thinks the correct term for this is "netfilter mark". A google search finds references to "netfilter mark" back to 2001, and with "fwmark" current at least to 2003. Both terms seem to be in use. The various netfilter HOWTOs don't say anything about new terminology. Horms (who wrote the fwmark code) doesn't know anything about a change in terminology, but thinks it's possible that fwmark is the implementation of netfilter marks.
I asked Harald Welte about this at OLS_2004 and the explanation was as clear as day, except that I didn't write it down and now I've forgotten it (geez, sorry about this). It was a matter of nomenclature rather than logic: it was something like - the entity in the command line is called a mark while the method of marking packets is called fwmark. Whatever it is, you can use either term and people will know what you're talking about.
fwmark實際上就是netfilter mark, 一種打標簽的方式或者實現, 沒有特殊的含義.
例一
內網的客戶機通過Linux主機連入Internet,而Linux主機有兩個網口與Internet連接, 分別有兩條線路,它們的網關分別為10.10.1.1和10.10.2.1. 現要求對內網進行策略路由,所有通過TCP協議訪問80端口的數據包都從10.10.1.1 線路出去,而所有訪問UDP協議53號端口的數據包都從10.10.2.1線路出去。
這是一個策略路由的問題,為了達到目的,在對數據包進行路由前,要先根據數據包的協議和目的端口給數據包做上一種標志,然后再指定相應規則,根據數據包的標志進行策略路由。為了給特定的數據包做上標志,需要使用mangle表,mangle表共有5條鏈,由於需要在路由選擇前做標志,因此應該使用PREROUTING鏈,下面是具體的命令。
iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -i eth0 -p udp --dprot 53 -j MARK --set-mark 2
以上命令在mangle表的PREROUTING鏈中添加規則,為來自eth0接口的數據包做標志,其匹配規則分別是TCP協議、目的端口號是80和UDP協議、目的端口號是53,標志的值分別是1和2。數據包經過PREROUTING鏈后,將要進入路由選擇模塊,為了對其進行策略路由,執行以下兩條命令,添加相應的規則
編輯 /etc/iproute2/rt_tables
, 添加對應的路由表
`echo -e "${TABLEID}\t${TABLENAME}" >> /etc/iproute2/rt_tables`
添加路由
ip rule add from all fwmark 1 table 10
ip rule add from all fwmark 2 table 20
以上兩條命令表示所有標志是1的數據包使用路由表10進行路由,而所有標志是2的數據包使用路由表20進行路由。路由表10和20分別使用了10.10.1.1和10.10.2.1作為默認網關
ip route add default via 10.10.1.1 dev eth1 table 10
ip route add default via 10.10.2.1 dev eth2 table 20
以上兩條命令在路由表10和20上分別指定了10.10.1.1和10.10.2.1作為默認網關, 於是使用路由表10的數據包將通過10.10.1.1線路出去,而使用路由表20的數據包將通過10.10.2.1線路出去
例二
網關服務器三塊網卡
- eth0 網通ip:10.0.0.1
- eth1 電信ip:20.0.0.1
- eth2 網關ip:192.168.10.1
內網要求192.168.10.1---100以內的ip使用10.0.0.1 網關上網, 其他IP使用 20.0.0.1上網
ip route add default gw 20.0.0.1
# eth0 是 10.0.0.1 所在的網卡, 10是路由表的編號
ip route add table 10 via 10.0.0.1 dev eth0
#fwmark 10 是標記, table 10 是路由表10, 標記了10的數據使用table 10路由表
ip rule add fwmark 10 table 10
#使用iptables給相應的數據打上標記, 對於這種IP范圍需要用到iprange模塊
iptables -A PREROUTING -t mangle -i eth2 -m iprange --src-range 192.168.10.1-192.168.10.100 -j MARK --set-mark 10
例三
網關服務器三塊網卡
- eth0 網通ip:10.0.0.1
- eth1 電信ip:20.0.0.1
- eth2 網關ip:192.168.10.1
內網要求員工訪問外面的網站使用 10.0.0.1 網關上網, 其他IP使用 20.0.0.1 上網
iptables -t mangle -A PREROUTING -i eth2 -p tcp --dport 80 -j MARK --set-mark 20
ip route add default gw 20.0.0.1
ip route add table 20 via 10.0.0.1 dev eth0
ip rule add fwmark 20 table 20
例四
使用dnsmasq, 將一個域名列表中匹配的域名解析得到的IP都放到一個名稱為outside的ipset中, 讓這個ipset的數據包都走指定的虛擬網卡
添加路由表
echo "200 outside" >> /etc/iproute2/rt_tables
添加ipset
# vi /etc/rc.local
ipset create outside hash:ip
添加iptables規則, 打標簽
將匹配 ipset outside的包全部標上 mark 8, 在 /etc/firewall.user 中添加:
# vi /etc/firewall.user
iptables -t mangle -A fwmark -m set --match-set outside dst -j MARK --set-mark 8
指定使用的路由表
# 讓 8.8.8.8 走 VPN,防止 DNS 污染
ip route add 8.8.8.8 dev $TUNDEV
ip route add default dev $TUNDEV table outside
ip rule add fwmark 8 table outside
將$TUNDEV替換為 VPN 設備名,比如ppp0, tun0等
配置dnsmasq, 使其解析時動態添加ipset
修改 /etc/dnsmasq.conf,在其中加入需要翻越的域名。 格式如下:
server=/域名/8.8.8.8
ipset=/域名/outside
其他
iptables: No chain/target/match by that name
# iptables -t mangle -A PREROUTING -s 192.168.2.0/24 -j
MARK --set-mark 1
iptables: No chain/target/match by that name
如果出現這個錯誤, 用下面的方式解決
[root@mpc8315erdb /root]# modprobe xt_MARK