ADSL 을 pppoe 로 컴터에 붙인뒤..
그걸 마스커레이딩 하면 특정 사이트에 접속이 안되는
널리 알려진 문제가 있습니다.
일반적으로 클라이언트의 MTU 를 줄여서 해결하는데..
이게 와 생기는 문제인가 하면..
tcp 외의 기타 프로토콜은 문제가 없는데..
tcp 의 경우 SYN handshaking 할때, TCP MSS 라는 (TCP Max Segment Size)
한번에 보낼 수 있는 최대 TCP packet size 를 상대방에게 알려줍니다.
이는 나가는 쪽 인터페이스를 기준으로 해서 계산되는데..
보통 ethernet protocol 의 MTU 가 1500 이므로.. (Max Transfer Unit)
IP header 20 byte 와 TCP header 20 byte 를 빼서
1460 을 TCP MSS 로 보내게 됩니다.
근데.. pppoe 접속한 뒤 컴의 경우..
pppoe encapsulation 때문에 8byte 를 더 쓰게 됩니다.
ethernet (MTU 1500) 위에 얹히는 pppoe 이기 때문에..
저기서 8을 뺀 1492가 ppp 디바이스의 MTU 값이 되죠.
한통/하나로 -=<PPPOE>=- [마스커 서버] -=<Ethernet>=- [뒤 컴터]
이런 식으로 내부 네트웍이 구성되는데..
마스커 하는 서버의 경우.. 게이트웨이가 ppp 이기 때문에
TCP MSS 값을 알아서 8 줄인 1452 로 계산해 패킷을 보내지만..
뒤 컴터는 게이트웨이가 마스커 서버이고..
그 디바이스가 이더넷이기 때문에, 평소하고 똑같이
TCP MSS 를 1460 으로 세팅해 패킷을 보내게 됩니다.
[뒤 컴터] 가 aaa.com 서버에 접속을 한다고 가장했을때..
1460 TCP MSS 로 TCP session 이 이루어제게 되면,
작은 패킷은 상관이 없지만.. 1460 이상의 큰 tcp 패킷에 대해선
aaa.com 서버에서 TCP MSS 1460 에 맞춰서 패킷을 fragment 하고..
IP header 의 don't fragment flag 를 켜서 패킷을 보내게 됩니다.
TCP/IP 헤더가 붙게 되면 이 패킷의 사이즈는 1500 이 되고..
그러면 이 패킷은 pppoe 때문에 MTU 가 8 줄어들어 1492 가 최대인
pppoe 터널을 통과하지 못하게 되고 drop 됩니다.
이때.. drop 시키는 라우터에서, aaa.com 서버 쪽으로
destination-unreachable / fragmentation-needed 라고 ICMP 패킷을 보내서
이건 쪼개보내라.. 라고 이야기하는데..
이런 ICMP 패킷이 필터링된다면 aaa.com 은 이 패킷이 잘 간줄 알고
그 패킷을 작게 재전송하지 않죠.
따라서 특정 사이트에서 큰 그림이나 파일을 열때 계속 먹통이 되죠.
서버는 보내고 클라이언트는 못받으니까..
여기까지가 왜 이런 일이 발생하는지에 대한 기술적인 설명이고..
일반적인 fix around 는 클라이언트의 MTU 를 조정하는것입니다.
클라이언트에서 MTU 를 줄여서 첨부터 큰 TCP MSS 가 붙은
SYN packet 을 보내지 못하게 하면 일단 문제는 해결되죠.
근데 모든 클라이언트를 변경해야 하는 큰 단점이 있습니다.
그래서.. kernel 2.4 iptables 에 이에 대한 해결책이 있습니다.
<i>
TCPMSS target support
CONFIG_IP_NF_TARGET_TCPMSS
This option adds a `TCPMSS' target, which allows you to alter the
MSS value of TCP SYN packets, to control the maximum size for that
connection (usually limiting it to your outgoing interface's MTU
minus 40).
This is used to overcome criminally braindead ISPs or servers which
block ICMP Fragmentation Needed packets. The symptoms of this
problem are that everything works fine from your Linux
firewall/router, but machines behind it can never exchange large
packets:
1) Web browsers connect, then hang with no data received.
2) Small mail works fine, but large emails hang.
3) ssh works fine, but scp hangs after initial handshaking.
Workaround: activate this option and add a rule to your firewall
configuration like:
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN
-j TCPMSS --clamp-mss-to-pmtu
</i>
kernel Documentation/Configure.help 의 내용이고..
Networking options --->
IP: Netfilter Configuration --->
IP tables support (required for filtering/masq/NAT)
를 활성화한뒤..
TCPMSS target support
를 Y 나 M 으로 켜고 커널을 다시 컴파일합니다.
그 뒤에 위와 같이..
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
이렇게 해주게 되면..
알아서 마스커레이딩 하는 패킷들의 TCP MSS 값을 재조정합니다.
그러면 클라이언트 컴퓨터들의 조정 없이 이 문제가 해결됩니다.