| Summary: | implement rfc1122 3.2.2.1, react to ICMP administratively prohibited | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | jesper <jesper> | ||||
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | CC: | jesper | ||||
| Priority: | Normal | ||||||
| Version: | 5.0-CURRENT | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
State Changed From-To: open->closed Committed, thanks! |
We currently does not react to ICMP administratively prohibited messages send by routers when they deny our traffic, this causes a timeout when trying to connect to TCP ports/services on a remote host, which is blocked by routers or firewalls. rfc1122 (Requirements for Internet Hosts) section 3.2.2.1 actually require that we treat such a message for a TCP session, that we treat it like if we had recieved a RST. quote begin. A Destination Unreachable message that is received MUST be reported to the transport layer. The transport layer SHOULD use the information appropriately; for example, see Sections 4.1.3.3, 4.2.3.9, and 4.2.4 below. A transport protocol that has its own mechanism for notifying the sender that a port is unreachable (e.g., TCP, which sends RST segments) MUST nevertheless accept an ICMP Port Unreachable for the same purpose. quote end. I've written a small extension that implement this, it also create a sysctl "net.inet.tcp.icmp_admin_prohib_like_rst" to control if this new behaviour is activated. When it's activated (set to 1) we'll treat a ICMP administratively prohibited message (icmp type 3 code 9, 10 and 13) for a TCP sessions, as if we recived a TCP RST, but only if the TCP session is in SYN_SENT state. The reason for only reacting when in SYN_SENT state, is that this will solve the problem, and at the same time minimize the risk of this being abused. I suggest that we enable this new behaviour by default, but it would be a change of current behaviour, so if people prefer to leave it disabled by default, at least for now, this would be ok for me, the attached diff actually have the sysctl set to 0 by default. Fix: Apply the below diff How-To-Repeat: Try to telnet to any host where this is blocked by a router/firewall that sends ICMP administratively prohibited messages, and do this with this sysctl set to 0 and to 1, like below: tam# sysctl -w net.inet.tcp.icmp_admin_prohib_like_rst=0 net.inet.tcp.icmp_admin_prohib_like_rst: 1 -> 0 tam# time telnet 193.89.247.125 25 Trying 193.89.247.125... telnet: connect to address 193.89.247.125: Connection refused telnet: Unable to connect to remote host 0.012u 0.000s 0:45.06 0.0% 88+164k 0+0io 0pf+0w tam# sysctl -w net.inet.tcp.icmp_admin_prohib_like_rst=1 net.inet.tcp.icmp_admin_prohib_like_rst: 0 -> 1 tam# time telnet 193.89.247.125 25 Trying 193.89.247.125... telnet: connect to address 193.89.247.125: Connection refused telnet: Unable to connect to remote host 0.012u 0.000s 0:00.06 16.6% 88+152k 0+0io 0pf+0w This saved 45 seconds ...