PPPoE 在 iptables 中 TCPMSS 設定問題
前言
前一陣子, 想要拿我的 CubieBoard 來當做家裡的firewall, 於是安裝了Debian 7, 並使用pppoe 來連接中華電信的Router, 並且寫了一些iptables 的rules 來當作firewall 及NAT router.
但是總是覺得有問題, 有時連不出去. 現象是這樣的:
這台Cubieboard 連線都很ok, 但是在NAT 後面的電腦, 只要碰上https 的連線, 有時就連不上, 但是用http 就ok, ftp 也ok.
這問題擺了很久都沒去理會. 今天終於有空好好的來追問題的源頭. 發現好像是跟pppoe 有關.
上網查了一下資料, 也順便學習了許多相關知識, 終於解決了問題.
MTU
MTU (Maximum Transmission Unit) 是指網路介面卡上最大傳輸單元, 其單位為bytes. 在大多數的Ehternet 上, 這個值通常是1500. 因為如此, 在PPPoE 中, 因為還有header問題, 所以這個值就得設的比較小, 通常為1492 (= 1500 – 2(PPP)- 6(PPPoE))
MSS
MSS (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 filter
iptables -X -t filter
iptables -Z -t filter
iptables -F -t mangle
iptables -X -t mangle
iptables -Z -t mangle
iptables -F -t nat
iptables -X -t nat
iptables -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
就搞定了!!
參考資料
- 最大傳輸單元
- Maximum segment size
- Can’t connect to certain HTTPS sites
- Installing Debian from the start a PPPoE enabled system
- pppoeconf not setting correct MTU
- 修改 MSS 解決 Linux PPPOE NAT 後部份網頁無法瀏覽問題
- How to Setup a Linux Firewall with PPPoE/NAT/iptables
- IP over IP tunnels & MTU problems
- 小議TCP的MSS(最大分段)以及MTU
- TCP中的MSS解读
- MTU原理及相關問題分析
您好,請問您有試過用CB4官方版的Ubuntu IMG做PPPoE的共用嗎? 我使用PPPoE可以撥號成功,但是CB4自己跟周圍的電腦都無法連到Internet。請問有什麼方法可以解決?
以下是官方下載點:
桌面版:
http://dl.cubieboard.org/model/cc-a80/Image/ubuntu-linaro/
server版:
http://dl.cubieboard.org/model/cc-a80/Image/ubuntu-linaro-server/
(1) 我沒有使用官方的Image. 我所使用的全部都是自己build 的image.
(2) 若是PPPoE撥號成功, 應該會產生一個新的network interface 叫做ppp0, 這時你可以檢查一下你的routing table(使用route指令), 看看default 的interface 是否為ppp0 ? 若不是的話, 你需要修改routing table. 若還有問題, 也有可能是你的iptable rule 設定不正確造成.
1. rootfs 也是自己build的? 需要combine官方的rootfs嗎? 官方的rootfs裡面好像有些補釘之類的東西
2. 我只有用CB4上面的網卡,eth0 static 。routing table有改過,指令用這樣”sudo route add default dev ppp0″,但還是上不去網際網路。
3. 有什麼方式可以在rootfs 預先安裝想要的package? 或者是把img 檔內的再加裝package?
(1) 我的rootfs 及kernel 都是自己build的. 請參考: http://blog.haostudio.net/hwp/%E5%8B%95%E6%89%8B%E6%89%93%E9%80%A0debian-root-filesystem-for-arm-2/
以及
http://blog.haostudio.net/hwp/%E5%BE%9Esource-code-%E9%96%8B%E5%A7%8B%E6%89%93%E9%80%A0%E6%9C%80%E5%9F%BA%E6%9C%AC%E7%9A%84debian-linux-system/
(2) 我猜測有可能你的kernel 在編譯時, 沒有將ppp 的相關driver編譯進去. 若真的是這樣的話, 即使是安裝pppoe的套件, 仍然無法使用ppp.
(3) 若要安裝套件, 先想辦法用eth0 上網, 例如拿機器到可以用dhcp 的環境, 先上網, 然後用apt-get 指令安裝你想要的套件.