顯示具有 netfilter 標籤的文章。 顯示所有文章
顯示具有 netfilter 標籤的文章。 顯示所有文章

2018年5月16日 星期三

相同的connection只會中NAT table的rule一次,其餘就不會進去

網路拓撲
[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 花了我一天半




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