redirect bug? was Re: Still no proxy access

bof@oknodo.bof.de bof@oknodo.bof.de
Wed, 28 Jun 2000 18:56:20 +0200 (MEST)


--ELM962211380-1180-0_
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

Hi Stefan & all,

> ipchains reports the original destination port but iptables
> reports the translated port.
> 
> I got around that problem by running the transproxy on port
> 80 or hacking transproxy (making it ignoring the port information.)
> 
> But this is not a good solution.
> 
> Is this a bug in iptables or do I missed something.

You missed something, though it's probably easy to miss. In old times,
there were hacks in place making the user level library function
getsockname() return the real (instead of the local) destination,
for transproxied stuff. That horror stops with iptables, making place
for a nice clean getsockopt() solution, called SO_ORIGINAL_DST.
However, now every transproxy application must be taught to use that
getsockopt() call instead of getsockname().

In the netfilter cvs module, you can find a replacement function for
getsockname(), called nf_getsockname(), which has the same calling syntax
as the original one, and should properly work with older (non-netfilter)
kernels - it should even compile there (without the newer functionality).
As the source is very short, I'll append it to this mail.

I am running at least one transproxy application using the setup, without
any problems, using various 2.4.0-test1 kernels.

regards
  Patrick

--ELM962211380-1180-0_
Content-Type: text/plain; charset=ISO-8859-1
Content-Disposition: attachment; filename=nf_getsockname.c
Content-Description: netfilter/OLD/tools/nf_getsockname.c
Content-Transfer-Encoding: 7bit

/* nf_getsockname() - netfilter SO_ORIGINAL_DST variant of getsockopt()
 *
 * Within the new Linux netfilter framework, NAT functionality is cleanly
 * separated from the TCP/IP core processing. In old days, you could easily
 * retrieve the original destination (IP address and port) of a transparently
 * proxied connection by calling the normal getsockname() syscall.
 * With netfilter, getsockname() returns the real local IP address and port.
 * However, the netfilter code gives all TCP sockets a new socket option,
 * SO_ORIGINAL_DST, for retrieval of the original IP/port combination.
 *
 * This file implements a function nf_getsockname(), with the same calling
 * convention as getsockname() itself; it uses SO_ORIGINAL_DST, and if that
 * fails, falls back to using getsockname() itself.
 *
 * Public domain by Patrick Schaaf <bof@bof.de>
 */

#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <linux/netfilter_ipv4.h>

int nf_getsockname(int fd, struct sockaddr *sa, int *salen)
{
	if (*salen != sizeof(struct sockaddr_in)) {
		errno = EINVAL;
		return -1;
	}
#ifdef SO_ORIGINAL_DST
	if (0 == getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, salen)) {
		return 0;
	}
#endif
	return getsockname(fd, sa, salen);
}

--ELM962211380-1180-0_--