網路拓撲
[Host1 - DNS Server] em1: 192.168.246.101 / 255.255.255.0
[Host2 - DNS Client] em1: 192.168.246.102 / 255.255.255.0
在Host1加入一條nat規則,此規則只是要驗證
相同的connection只會中NAT table的rule一次,其餘就不會進去
Host1# iptables -t nat -A PREROUTING -i em1 -p udp -s 192.168.246.102 --j DNAT --to 192.168.246.101:53
把DNS回應封包Drop掉,Host1就會用相同的socket pair重送(dig預設重送三次)
Host1# iptables -A OUTPUT -p udp --sport 53 -j DROP
可加Log透過dmesg來追蹤封包
Host1# iptables -t mangle -A PREROUTING -i em1 -p udp --dport 53 -j LOG --log-level 4 --log-prefix MANGLE_TEST:
Host1# iptables -t nat -I PREROUTING -i em1 -p udp --dport 53 -j LOG --log-level 4 --log-prefix NAT_TEST:
Host1# iptables -A INPUT -i em1 -p udp --dport 53 -j LOG --log-level 4 --log-prefix INPUT_TEST:
從Host2利用dig產生DNS查詢封包到Host1
Host2# dig www.google.com @192.168.246.101
可觀察在NAT table的rule與conntrack,預設client會重送三次封包,match只會中一次
Host1# iptables -t nat -nvL PREROUTING
Chain PREROUTING (policy ACCEPT 8 packets, 566 bytes)
pkts bytes target prot opt in out source destination
1 71 LOG udp -- em1 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 LOG flags 0 level 4 prefix "NAT_TEST:"
1 71 DNAT udp -- em1 * 192.168.246.102 0.0.0.0/0 to:192.168.246.101:53
Host1# conntrack -L | grep 192.168.246.102
udp 17 177 src=192.168.246.102 dst=192.168.246.101 sport=51161 dport=53 src=192.168.246.101 dst=192.168.246.102 sport=53 dport=51161 [ASSURED] mark=0 use=1
注意事項: 要conntrack有這筆connection才會之後bypass NAT rule
參考連結:
packet 沒有跑到 iptables 的 nat table 花了我一天半
2018年5月16日 星期三
2017年8月29日 星期二
netfilter防火牆
Netfilter為Linux kernel的一個防火牆機制,
一般運作於L2 (Link Layer)跟L3 (Network Layer)之間,
使用者利用iptables或nftables這個utility,
來下一些規則到底層的netfilter模組去做控制 [註一],
規則的組成主要分為chain跟table這兩大項, 匹配原則主要是first match。
chain1 PREROUTING
chain2 INPUT
chain3 FORWARD
chain4 OUTPUT
chain5 POSTROUTING
table1 filter (預設): limit
table2 nat: DNAT, SNAT, redirect
table3 mangle: mark, tos
table4 raw: connection tracking
下面說明當收到一個封包進來時,是如何處理的流程:
RX
當封包進來時,經由Layer1的NIC收到,根據這個封包的
4-tuple (source ip, source port, destination ip, destination port)
hash完交由cpu某一個core來處理,到了Layer2的NIC driver處理完之後
每個封包就會以skb的結構去呈現運作 [註二]。
當封包為route mode往上走到Layer3會檢查checksum validation
當checksum有問題就會丟棄這個封包,
之後開始進入netfilter的hook處理點,
經由PREROUTING處理完之後會查詢routing table
決定這封包的機會(deliver到INPUT)與命運(forward到FORWARD)
如果這封包是deliver上面給這台主機去處理的話,
通常會在INPUT上面的filter去下規則來limit保護;
反之,這封包是要forward出去的話 [註三],
就會在FORWARD上面的filter去下規則來limit保護。
一般封包目的端都是本機,所以查詢routing table之後
封包會deliver往上到INPUT處理,再經由Transport Layer的socket去處理
所以一般在user space上寫應用程式
來接收複製socket裡面的封包到user space的buffer來處理 [註四]
TX
當應用程式處理完要回應封包時,會把這個message送往socket處理
然後查詢routing table決定EGRESS的介面是那一個,
然後經由OUTPUT->POSTROUTING->NIC driver送往NIC出去
[註一]
# lsmod | grep table
ip6table_filter 12815 1
ip6_tables 26902 1 ip6table_filter
iptable_filter 12810 1
ip_tables 27116 1 iptable_filter
x_tables 34802 4 ip6table_filter,ip_tables,iptable_filter,ip6_tables
[註二]
一般常用抓封包的tcpdump是運作於Layer2,所以針對INGRESS進來的封包
下符合條件封包規則drop丟棄( L3),在tcpdump還是可以看到此封包。
[註三]
啟動forward: echo 1 > /proc/sys/net/ipv4/ip_forward
經過FORWARD的封包TTL會減一,通常避免會有loop產生
例子: 無線IP分享器,大多數封包都是走forward,除非是要更改設定那台的設定,封包才會deliver到本機的網頁去做設定的動作。
[註四]
基本上一個封包進來會被複製copy兩次
NIC -> skb buffer
skb buffer -> user buffer
訂閱:
文章 (Atom)
