From owner-freebsd-net@FreeBSD.ORG Fri Sep 23 17:51:38 2005 Return-Path: X-Original-To: net@freebsd.org Delivered-To: freebsd-net@FreeBSD.ORG Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BABFE16A42A for ; Fri, 23 Sep 2005 17:51:38 +0000 (GMT) (envelope-from cristjc@comcast.net) Received: from rwcrmhc12.comcast.net (rwcrmhc14.comcast.net [216.148.227.89]) by mx1.FreeBSD.org (Postfix) with ESMTP id 683D243D45 for ; Fri, 23 Sep 2005 17:51:38 +0000 (GMT) (envelope-from cristjc@comcast.net) Received: from goku.cjclark.org (c-24-6-184-207.hsd1.ca.comcast.net[24.6.184.207]) by comcast.net (rwcrmhc14) with ESMTP id <2005092317513601400omme7e>; Fri, 23 Sep 2005 17:51:37 +0000 Received: from goku.cjclark.org (localhost. [127.0.0.1]) by goku.cjclark.org (8.13.3/8.12.8) with ESMTP id j8NHpTuM069441 for ; Fri, 23 Sep 2005 10:51:30 -0700 (PDT) (envelope-from cristjc@comcast.net) Received: (from cjc@localhost) by goku.cjclark.org (8.13.3/8.13.1/Submit) id j8NHpPPo069440 for net@freebsd.org; Fri, 23 Sep 2005 10:51:26 -0700 (PDT) (envelope-from cristjc@comcast.net) X-Authentication-Warning: goku.cjclark.org: cjc set sender to cristjc@comcast.net using -f Date: Fri, 23 Sep 2005 10:51:25 -0700 From: "Crist J. Clark" To: net@freebsd.org Message-ID: <20050923175125.GA69254@goku.cjclark.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.1i X-URL: http://people.freebsd.org/~cjc/ Cc: Subject: Fixed Dest Port for traceroute(8) X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: "Crist J. Clark" List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Sep 2005 17:51:38 -0000 Gee. It would be nice if one could fix the outgoing port for UDP and TCP traceroutes. Sometimes firewalls, load balancers, and various other systems treat packets differently depending on the transport layer destination port. The current traceroute implementation allows one to specify a starting port, but increments the port with each packet sent out. It doesn't do this without reason. The value is essentially a sequence number that is used to identify out-of-order responses, but this screws up our ability to traceroute a specific port. Also, traceroute just needs more options. It's closing on ping(8). I have added a '-e' option. A firewall "evasion," fixed-port option. For TCP and UDP scans, the destination port is not changed. Doing this in TCP is pretty straightforward. The sequence number field was already being loaded with the source port (which in turn is the PID) and destination port. I stopped incrementing the destination port, but continiued to increment the dest port part of the sequence number. I added the sequence number to the out-of-order check. For UDP, that approach won't work. There isn't much space available in the header to store a counter, so I switched the conter to the source port rather than destination. I thought about abusing the UDP checksum. But that has the side effect that the destination will drop our last packet rather than return a port unreachable and has the potential to confuse NATing devices and other nastiness (although we somehow got away without TCP checksums at all for a long time). The counter is only switched when the fixed port option is given. Anyone mind if I see if my commit bit still works and merge this in? Index: traceroute.8 =================================================================== RCS file: /ncvs/freebsd/src/contrib/traceroute/traceroute.8,v retrieving revision 1.11 diff -u -r1.11 traceroute.8 --- traceroute.8 12 Apr 2005 15:16:32 -0000 1.11 +++ traceroute.8 23 Sep 2005 17:47:12 -0000 @@ -24,7 +24,7 @@ .na .B traceroute [ -.B \-dFISdnrvx +.B \-deFISdnrvx ] [ .B \-f .I first_ttl @@ -98,6 +98,11 @@ .PP Other options are: .TP +.B \-e +Firewall evasion mode. +Use fixed destination ports for UDP and TCP probes. +The destination port does NOT increment with each packet sent. +.TP .B \-f Set the initial time-to-live used in the first outgoing probe packet. .TP Index: traceroute.c =================================================================== RCS file: /ncvs/freebsd/src/contrib/traceroute/traceroute.c,v retrieving revision 1.27 diff -u -r1.27 traceroute.c --- traceroute.c 26 Aug 2005 18:08:24 -0000 1.27 +++ traceroute.c 23 Sep 2005 17:47:45 -0000 @@ -353,6 +353,7 @@ int doipcksum = 1; /* calculate ip checksums by default */ #endif int optlen; /* length of ip options */ +int fixedPort = 0; /* Use fixed destination port for TCP and UDP */ extern int optind; extern int opterr; @@ -521,13 +522,17 @@ prog = argv[0]; opterr = 0; - while ((op = getopt(argc, argv, "dFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) + while ((op = getopt(argc, argv, "edFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) switch (op) { case 'd': options |= SO_DEBUG; break; + case 'e': + fixedPort = 1; + break; + case 'f': case 'M': /* FreeBSD compat. */ first_ttl = str2val(optarg, "first ttl", 1, 255); @@ -1289,8 +1294,8 @@ { struct udphdr *const outudp = (struct udphdr *) outp; - outudp->uh_sport = htons(ident); - outudp->uh_dport = htons(port + outdata->seq); + outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0)); + outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq)); outudp->uh_ulen = htons((u_short)protlen); outudp->uh_sum = 0; if (doipcksum) { @@ -1306,8 +1311,8 @@ { struct udphdr *const udp = (struct udphdr *) data; - return (ntohs(udp->uh_sport) == ident - && ntohs(udp->uh_dport) == port + seq); + return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) && + ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq)); } void @@ -1316,8 +1321,9 @@ struct tcphdr *const tcp = (struct tcphdr *) outp; tcp->th_sport = htons(ident); - tcp->th_dport = htons(port + outdata->seq); - tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport; + tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq)); + tcp->th_seq = (tcp->th_sport << 16) | (tcp->th_dport + + (fixedPort ? outdata->seq : 0)); tcp->th_ack = 0; tcp->th_off = 5; tcp->th_flags = TH_SYN; @@ -1335,7 +1341,8 @@ struct tcphdr *const tcp = (struct tcphdr *) data; return (ntohs(tcp->th_sport) == ident - && ntohs(tcp->th_dport) == port + seq); + && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq)) + && tcp->th_seq == (ident << 16) | (port + seq); } void -- Crist J. Clark | cjclark@alum.mit.edu