git: f1cfcfb2e51a - main - traceroute6: implement firewall evasion mode

From: Eugene Grosbein <eugen_at_FreeBSD.org>
Date: Sun, 16 Aug 2026 08:32:59 UTC
The branch main has been updated by eugen:

URL: https://cgit.FreeBSD.org/src/commit/?id=f1cfcfb2e51ae5afa8941342ad10f650db8279c5

commit f1cfcfb2e51ae5afa8941342ad10f650db8279c5
Author:     Eugene Grosbein <eugen@FreeBSD.org>
AuthorDate: 2026-08-16 08:29:20 +0000
Commit:     Eugene Grosbein <eugen@FreeBSD.org>
CommitDate: 2026-08-16 08:31:57 +0000

    traceroute6: implement firewall evasion mode
    
    Merge implementation of "traceroute -e" to traceroute6 for TCP/UDP/SCTP.
    
    MFC-after:      2 weeks
---
 usr.sbin/traceroute6/traceroute6.8 |  8 ++++++--
 usr.sbin/traceroute6/traceroute6.c | 28 ++++++++++++++++------------
 2 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/usr.sbin/traceroute6/traceroute6.8 b/usr.sbin/traceroute6/traceroute6.8
index 406a96a04424..7c6890d4de6a 100644
--- a/usr.sbin/traceroute6/traceroute6.8
+++ b/usr.sbin/traceroute6/traceroute6.8
@@ -27,7 +27,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd November 12, 2024
+.Dd August 16, 2026
 .Dt TRACEROUTE6 8
 .Os
 .\"
@@ -38,7 +38,7 @@
 .Sh SYNOPSIS
 .Nm
 .Bk -words
-.Op Fl adEIlnNrSTUv
+.Op Fl adeEIlnNrSTUv
 .Ek
 .Bk -words
 .Op Fl A Ar as_server
@@ -92,6 +92,10 @@ Turn on AS# lookups for each hop encountered.
 Turn on AS# lookups and use the given server instead of the default.
 .It Fl d
 Debug mode.
+.It Fl e
+Firewall evasion mode.
+Use fixed destination ports for UDP, TCP and SCTP probes.
+The destination port does NOT increment with each packet sent.
 .It Fl E
 Detect ECN bleaching.
 Set the
diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c
index eb6086706f9f..7b821c11db38 100644
--- a/usr.sbin/traceroute6/traceroute6.c
+++ b/usr.sbin/traceroute6/traceroute6.c
@@ -333,6 +333,7 @@ static u_long max_hops = 30;
 static u_int16_t srcport;
 static u_int16_t port = 32768 + 666;	/* start udp dest port # for probe packets */
 static u_int16_t ident;
+static int fixedPort = 0;	/* Use fixed destination port for TCP/UDP/SCTP */
 static int tclass = -1;
 static int options;			/* socket options */
 static int verbose;
@@ -402,7 +403,7 @@ main(int argc, char *argv[])
 	seq = 0;
 	ident = htons(getpid() & 0xffff); /* same as ping6 */
 
-	while ((ch = getopt(argc, argv, "aA:dEf:g:Ilm:nNp:q:rs:St:TUvw:")) != -1)
+	while ((ch = getopt(argc, argv, "aA:deEf:g:Ilm:nNp:q:rs:St:TUvw:")) != -1)
 		switch (ch) {
 		case 'a':
 			as_path = 1;
@@ -414,6 +415,9 @@ main(int argc, char *argv[])
 		case 'd':
 			options |= SO_DEBUG;
 			break;
+		case 'e':
+			fixedPort = 1;
+			break;
 		case 'E':
 			ecnflag = 1;
 			break;
@@ -1136,8 +1140,8 @@ send_probe(int seq, u_long hops)
 		break;
 	case IPPROTO_UDP:
 		outudp = (struct udphdr *) outpacket;
-		outudp->uh_sport = htons(ident);
-		outudp->uh_dport = htons(port + seq);
+		outudp->uh_sport = htons(ident + (fixedPort ? seq : 0));
+		outudp->uh_dport = htons(port  + (fixedPort ? 0 : seq));
 		outudp->uh_ulen = htons(datalen);
 		outudp->uh_sum = 0;
 		outudp->uh_sum = udp_cksum(&Src, &Dst, outpacket, datalen);
@@ -1149,7 +1153,7 @@ send_probe(int seq, u_long hops)
 		sctp = (struct sctphdr *)outpacket;
 
 		sctp->src_port = htons(ident);
-		sctp->dest_port = htons(port + seq);
+		sctp->dest_port = htons(port + (fixedPort ? 0 : seq));
 		if (datalen >= (u_long)(sizeof(struct sctphdr) +
 		    sizeof(struct sctp_init_chunk))) {
 			sctp->v_tag = 0;
@@ -1215,7 +1219,7 @@ send_probe(int seq, u_long hops)
 		tcp = (struct tcphdr *)outpacket;
 
 		tcp->th_sport = htons(ident);
-		tcp->th_dport = htons(port + seq);
+		tcp->th_dport = htons(port + (fixedPort ? 0 : seq));
 		tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
 		tcp->th_ack = 0;
 		tcp->th_off = 5;
@@ -1423,14 +1427,14 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code,
 			break;
 		case IPPROTO_UDP:
 			udp = (struct udphdr *)up;
-			if (udp->uh_sport == htons(ident) &&
-			    udp->uh_dport == htons(port + seq))
+			if (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
+			    ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq))
 				return (1);
 			break;
 		case IPPROTO_SCTP:
 			sctp = (struct sctphdr *)up;
-			if (sctp->src_port != htons(ident) ||
-			    sctp->dest_port != htons(port + seq)) {
+			if (ntohs(sctp->src_port) != ident ||
+			    ntohs(sctp->dest_port) != port + (fixedPort ? 0 : seq)) {
 				break;
 			}
 			if (datalen >= (u_long)(sizeof(struct sctphdr) +
@@ -1457,8 +1461,8 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code,
 			break;
 		case IPPROTO_TCP:
 			tcp = (struct tcphdr *)up;
-			if (tcp->th_sport == htons(ident) &&
-			    tcp->th_dport == htons(port + seq) &&
+			if (ntohs(tcp->th_sport) == ident &&
+			    ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq) &&
 			    tcp->th_seq ==
 			    (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
 				return (1);
@@ -1842,7 +1846,7 @@ void
 usage(void)
 {
 	fprintf(stderr,
-"Usage: traceroute6 [-adEIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
+"Usage: traceroute6 [-adeEIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
 "\t[-m hoplimit] [-p port] [-q probes] [-s src] [-t tclass]\n"
 "\t[-w waittime] target [datalen]\n");
 	exit(1);