前言 前一陣子, 想要拿我的 CubieBoard 來當做家裡的firewall, 於是安裝了Debian 7, 並使用pppoe 來連接中華電信的Router, 並且寫了一些iptables 的rules 來當作firewall 及NAT router.
但是總是覺得有問題, 有時連不出去. 現象是這樣的: 這台Cubieboard 連線都很ok, 但是在NAT 後面的電腦, 只要碰上https 的連線, 有時就連不上, 但是用http 就ok, ftp 也ok. 這問題擺了很久都沒去理會. 今天終於有空好好的來追問題的源頭. 發現好像是跟pppoe 有關.
上網查了一下資料, 也順便學習了許多相關知識, 終於解決了問題. MTUMTU (Maximum Transmission Unit) 是指網路介面卡上最大傳輸單元, 其單位為bytes. 在大多數的Ehternet 上, 這個值通常是1500. 因為如此, 在PPPoE 中, 因為還有header問題, 所以這個值就得設的比較小, 通常為1492 (= 1500 – 2(PPP)- 6(PPPoE)) MSSMSS (Maximum segment size) 是TCP protocol 中的一個參數, 是指TCP 每次資料傳輸分段的最大值. 當TCP 在handshake 時, 雙方host 會查看MSS 這個欄位, 來決定雙方資料傳輸分段的大小. 在Ethernet 中MSS 值最大為1460 bytes.
原因是在Ethernet 中 MTU = IP Header + TCP Header + MSS + FCS.
(FCS 是指Frame check sequence, 通常採用CRC演算法, 在Ethernet 中, 它佔4 bytes.)
但是在PPPoE 中MTU 為1492, 所以其MSS 只能設為1452. 問題所在當Debian 在開機後, 啟動了ppp0, 其內定將MTU 設為1492, 並且會自動設定一條iptable rule, 查看/etc/ppp/ip-up.d/0clampmss 得知如下: # cat /etc/ppp/ip-up.d/0clampmss #!/bin/sh# Enable MSS clamping (autogenerated by pppoeconf)iptables -t mangle -o "$PPP_IFACE" --insert FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu因為在NAT 後面的電腦, 並不知道前端的router 是用什麼介面連到internet, 所以它和遠端的電腦建立TCP 連線時, 有可能會將MSS 設為1460. 但是由於firewall 或router 端使用PPPoE連線, 若MSS 大於1452會造成資料爆掉, 所以上述的iptable rule 強制偷改其MSS值(在IPV4下 = PMTU – 40, 在IPV6下 = PMTU – 60). 因此MSS 就會被改成1452, 這樣子就不會爆掉了. 但是我自己寫的iptable rule script 中, 一開始就用了下列設定, 清除了原來的所有設定 # 清除所有規則iptables -F -t filteriptables -X -t filteriptables -Z -t filteriptables -F -t mangleiptables -X -t mangleiptables -Z -t mangleiptables -F -t natiptables -X -t natiptables -Z -t nat造成/etc/ppp/ip-up.d/0clampmss 的設定也被清除掉了, 然後NAT 後面的電腦就常常無法連線. 解決方式既然知道原因, 解法就很簡單, 就是在我自己的iptable rule 中再加上 iptables -t mangle -o ppp0 --insert FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu就搞定了!!
|