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