bin/54274: udp-proxy support is not implemented in libalias

Nicolai Petri nicolai at petri.cc
Wed Jul 9 13:00:39 PDT 2003


>Number:         54274
>Category:       bin
>Synopsis:       udp-proxy support is not implemented in libalias
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 09 13:00:33 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Nicolai Petri
>Release:        FreeBSD 4.8-STABLE i386
>Organization:
catpipe Systems ApS
>Environment:
System: FreeBSD unflink.catpipe.net 4.8-STABLE FreeBSD 4.8-STABLE #0: Sun Jun 29 22:08:46 CEST 2003 root at unflink.catpipe.net:/usr/src/sys/compile/UNFLINK i386

This problem applies to all FreeBSD releases.

>Description:
When doing a transparent gateway which I build on top of libalias, I discovered it was impossible to use proxy_rule functions for redirecting dns packets, because libalias does not implement this.
This patch implements the code for udp-proxying.  
NOTE: This should work both with stable and current because the changerate in libalias is very low.  
 
>How-To-Repeat:
	Try using creating a proxy_rule that uses udp in natd. 
>Fix:
	Patch :
--- alias.c.orig	Fri Nov  8 14:45:08 2002
+++ alias.c	Mon Nov 11 11:38:46 2002
@@ -257,7 +257,7 @@
 static int ProtoAliasIn(struct ip *);
 static int ProtoAliasOut(struct ip *);
 
-static int UdpAliasOut(struct ip *);
+static int UdpAliasOut(struct ip *, int);
 static int UdpAliasIn (struct ip *);
 
 static int TcpAliasOut(struct ip *, int);
@@ -744,28 +744,28 @@
     struct udphdr *ud;
     struct alias_link *link;
 
-/* Return if proxy-only mode is enabled */
-    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
-        return PKT_ALIAS_OK;
-
     ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
 
     link = FindUdpTcpIn(pip->ip_src, pip->ip_dst,
                         ud->uh_sport, ud->uh_dport,
-                        IPPROTO_UDP, 1);
+                        IPPROTO_UDP, !(packetAliasMode & PKT_ALIAS_PROXY_ONLY));
     if (link != NULL)
     {
         struct in_addr alias_address;
         struct in_addr original_address;
+        struct in_addr proxy_address;
         u_short alias_port;
+        u_short proxy_port;
         int accumulate;
         u_short *sptr;
-	int r = 0;
+        int r = 0;
 
         alias_address = GetAliasAddress(link);
         original_address = GetOriginalAddress(link);
+        proxy_address = GetProxyAddress(link);
         alias_port = ud->uh_dport;
         ud->uh_dport = GetOriginalPort(link);
+        proxy_port = GetProxyPort(link);
 
 /* Special processing for IP encoding protocols */
 	if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
@@ -791,14 +791,48 @@
             sptr = (u_short *) &original_address;
             accumulate -= *sptr++;
             accumulate -= *sptr;
+
+/* If this is a proxy packet, modify checksum because of source change.*/
+            if (proxy_port != 0)
+            {
+                accumulate += ud->uh_sport;
+                accumulate -= proxy_port;
+            }
+            
+	    if (proxy_address.s_addr != 0)
+            {
+	        sptr = (u_short *) &pip->ip_src;
+                accumulate += *sptr++;
+                accumulate += *sptr;
+                sptr = (u_short *) &proxy_address;
+                accumulate -= *sptr++;
+                accumulate -= *sptr;
+            }
+
             ADJUST_CHECKSUM(accumulate, ud->uh_sum);
+
         }
 
+/* XXX: Could the two if's below be concatenated to one ? */
+/* Restore source port and/or address in case of proxying*/
+
+	if (proxy_port != 0)
+            ud->uh_sport = proxy_port;
+
+	if (proxy_address.s_addr != 0)
+	{
+	    DifferentialChecksum(&pip->ip_sum,
+                   (u_short *) &proxy_address,
+                   (u_short *) &pip->ip_src,
+                   2);
+            pip->ip_src = proxy_address;
+	}
+
 /* Restore original IP address */
         DifferentialChecksum(&pip->ip_sum,
-                             (u_short *) &original_address,
-                             (u_short *) &pip->ip_dst,
-                             2);
+                         (u_short *) &original_address,
+                         (u_short *) &pip->ip_dst,
+                         2);
         pip->ip_dst = original_address;
 
 	/*
@@ -813,16 +847,57 @@
 }
 
 static int
-UdpAliasOut(struct ip *pip)
+UdpAliasOut(struct ip *pip, int maxpacketsize)
 {
     struct udphdr *ud;
     struct alias_link *link;
+    int proxy_type;
+    u_short dest_port;
+    u_short proxy_server_port;
+    struct in_addr dest_address;
+    struct in_addr proxy_server_address;
 
-/* Return if proxy-only mode is enabled */
-    if (packetAliasMode & PKT_ALIAS_PROXY_ONLY)
+/*	Return if proxy-only mode is enabled and not proxyrule found.*/
+	ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+
+	proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port);
+
+	if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY))
         return PKT_ALIAS_OK;
 
-    ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+/* If this is a transparent proxy, save original destination,
+   then alter the destination and adjust checksums */
+    dest_port = ud->uh_dport;
+    dest_address = pip->ip_dst;
+
+    if (proxy_type != 0)
+    {
+        int accumulate;
+        u_short *sptr;
+
+        accumulate = ud->uh_dport;
+        ud->uh_dport = proxy_server_port;
+        accumulate -= ud->uh_dport;
+
+        sptr = (u_short *) &(pip->ip_dst);
+        accumulate += *sptr++;
+        accumulate += *sptr;
+        sptr = (u_short *) &proxy_server_address;
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+        ADJUST_CHECKSUM(accumulate, ud->uh_sum);
+
+        sptr = (u_short *) &(pip->ip_dst);
+        accumulate  = *sptr++;
+        accumulate += *sptr;
+        pip->ip_dst = proxy_server_address;
+        sptr = (u_short *) &(pip->ip_dst);
+        accumulate -= *sptr++;
+        accumulate -= *sptr;
+
+        ADJUST_CHECKSUM(accumulate, pip->ip_sum);
+    }
 
     link = FindUdpTcpOut(pip->ip_src, pip->ip_dst,
                          ud->uh_sport, ud->uh_dport,
@@ -832,6 +907,17 @@
         u_short alias_port;
         struct in_addr alias_address;
 
+/* Save original destination address, if this is a proxy packet.
+   Also modify packet to include destination encoding.  This may
+   change the size of IP header. */
+        if (proxy_type != 0)
+        {
+            SetProxyPort(link, dest_port);
+            SetProxyAddress(link, dest_address);
+            ProxyModify(link, pip, maxpacketsize, proxy_type);
+            ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
+        }
+
         alias_address = GetAliasAddress(link);
         alias_port = GetAliasPort(link);
 
@@ -1092,7 +1178,7 @@
         else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
          || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
          || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
-         || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2) 
+         || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
             AliasHandleRtspOut(pip, link, maxpacketsize);
         else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
          || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
@@ -1434,7 +1520,7 @@
                 iresult = IcmpAliasOut(pip);
                 break;
             case IPPROTO_UDP:
-                iresult = UdpAliasOut(pip);
+                iresult = UdpAliasOut(pip, maxpacketsize);
                 break;
             case IPPROTO_TCP:
                 iresult = TcpAliasOut(pip, maxpacketsize);



>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list