Date: Wed, 9 Jul 2003 21:52:14 +0200 (CEST) From: Nicolai Petri <nicolai@petri.cc> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/54274: udp-proxy support is not implemented in libalias Message-ID: <200307091952.h69JqEdn068585@unlink.catpipe.net> Resent-Message-ID: <200307092000.h69K0YXK037966@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200307091952.h69JqEdn068585>