How to enable traceroute in linux machine

I'm working on something in the transport layer and after i ran our custom policies for securing the policies i'm not able to do traceroute from the linux machine.

root@keystone-evm:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:echo
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:isakmp
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:radius
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:ntp
ACCEPT     icmp --  anywhere             10.222.4.212
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:domain
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:bootpc
ACCEPT     udp  --  anywhere             10.222.4.212         udp dpt:bootps
ACCEPT     123  --  anywhere             10.222.4.212
DROP       all  --  anywhere             anywhere
ACCEPT     udp  --  anywhere             anywhere             udp spts:33434:33524 state NEW,RELATED,ESTABLISHED

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:echo
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:isakmp
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:radius
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:ntp
ACCEPT     icmp --  10.222.4.212         anywhere
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:domain
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:bootpc
ACCEPT     udp  --  10.222.4.212         anywhere             udp dpt:bootps
ACCEPT     123  --  10.222.4.212         anywhere
DROP       all  --  anywhere             anywhere
ACCEPT     udp  --  anywhere             anywhere             udp dpts:33434:33524 state NEW
root@keystone-evm:~# traceroute 10.222.4.100
traceroute to 10.222.4.100 (10.222.4.100), 30 hops max, 38 byte packets
 1traceroute: sendto: Operation not permitted

The given below is the command I issued to enable traceroute:

  • iptables -A OUTPUT -o eth0 -p udp --dport 33434:33524 -m state --state NEW -j ACCEPT
  • iptables -A INPUT -p udp --sport 33434:33524 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

We can see from man 8 traceroute that:

  • UDP is the default traceroute mechanism on Linux
  • traceroute expects to get an "ICMP unreachable" message in response to its query
  • traces start at port 33434 and increment by one for each hop

Meanwhile, Microsoft confirms that Windows uses "ICMP Echo Requests" in its implementation.

So, here is the answer to allow a host to correctly process inbound and perform outbound traceroutes. Append a rule to reject (not drop) traffic on UDP ports 33434-33474, and reply to echo requests, and allow the matching outbound packets as well, if you're restricting outbound traffic.

# reject (not drop) packets for inbound traceroutes from Linux boxes
iptables -I INPUT -p udp --dport 33434:33474 -j REJECT

# accept ping requests for Windows-style traceroutes
iptables -I INPUT -p ICMP --icmp-type echo-request -j ACCEPT

# allow ping responses for Windows-style traceroutes
iptables -I OUTPUT -p ICMP --icmp-type echo-reply -j ACCEPT

# allow the server to perform its own traceroutes
iptables -I OUTPUT -p udp --dport 33434:33474 -j ACCEPT

For the record, the excerpt from the man page:

LIST OF AVAILABLE METHODS
       In  general,  a  particular traceroute method may have to be chosen by -M name, but
       most of the methods have their simple cmdline switches (you can see them after  the
       method name, if present).

   default
       The traditional, ancient method of tracerouting. Used by default.

       Probe  packets  are udp datagrams with so-called "unlikely" destination ports.  The
       "unlikely" port of the first probe is 33434, then for each next probe it is  incre-
       mented by one. Since the ports are expected to be unused, the destination host nor-
       mally returns "icmp unreach port" as a final response.  (Nobody knows what  happens
       when some application listens for such ports, though).

       This method is allowed for unprivileged users.

   icmp       -I
       Most usual method for now, which uses icmp echo packets for probes.
       If you can ping(8) the destination host, icmp tracerouting is applicable as well.

   tcp        -T
       Well-known modern method, intended to bypass firewalls.
       Uses the constant destination port (default is 80, http).

Thanks for all the inputs.

I came up with a shell script to do the job for me. I believe this would be helpful for other users also to perform the task. Please note that the local machine IP. Please do the necessary changes accordingly.

#!/bin/sh
echo "Enabling Traceroute..."

#Outbound UDP traffic Policy

iptables -I OUTPUT -o eth0 -p udp --dport 33434:33524 -m state --state NEW -j ACCEPT

iptables -I INPUT -p udp --sport 33434:33524 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

#Inbound ICMP traffic Policy


iptables -I INPUT -p icmp --icmp-type 3/3 -d 10.222.4.212 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -I INPUT -p icmp --icmp-type 11  -d 10.222.4.212 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

First of all: the iptables -A command add the new rule after the end of your actual chains. They were processed only after the last rule in your chains. But it won't happen, because the last rule already filters everything out! You need to put these commands before your last rule, which can be done with the -I <n> flag of the iptables.

Second: Traceroute is working by sending ICMP packets, just as ping does. It is essentially a ping, which tries to get a list of the remote network nodes on the way to the target machine, by sending packets with low, but growing packet TTL fields.

I don't have any idea, from where you got this udp/33434 thing. If you want traceroute, enable ICMP, which doesn't have any ports.

Third: (reacting commect) It seems, sometimes traceroute don't use only simple icmp packets, but udp or even tcp packets as well. There is even a tool named tcptraceroute, which can do this last thing on a very good configurable way. If you aren't sure, check with strace or with a tcpdump, where your traceroute wants to actually communicate, and enable at least this port.