From: Martijn Lievaart <m@rtij.nl>
To: netfilter-devel@lists.netfilter.org
Subject: Strange MASQUERADING behaviour, bug or feature?
Date: Mon, 17 Apr 2006 23:46:58 +0200 [thread overview]
Message-ID: <44440CD2.6060006@rtij.nl> (raw)
[-- Attachment #1: Type: text/plain, Size: 3739 bytes --]
Hi,
[ Long story, better to much information than to little ]
I encountered some non-intuitive behaviour with MASQUERADE. I wrote a
dial-on-demand utility, that uses a tun interface. When it sees packets,
it brings up the real interface. However, packets are masqueraded with
the ip address of the tun interface, just like the testsetup below. As
the real interface is assigned an address with dhcp (the reason for
using masquerade in the first place), I cannot assign the real address
to the tun interface.
To reproduce this behaviour in a test setup, I wrote a small utility
that allocates a nullX device, a device that just discards all packets
send to it. It assigns a link local ipv4 address to that interface.
On the test machine (machine A, kernel 2.6.15) I set up these iptables
rules:
*nat
:OUTPUT ACCEPT [1463:59018]
:POSTROUTING ACCEPT [1468:59346]
:PREROUTING ACCEPT [1209:217623]
-A POSTROUTING -o null0 -j MASQUERADE
-A POSTROUTING -o null1 -j MASQUERADE
COMMIT
*filter
:FORWARD ACCEPT [647:54256]
:INPUT ACCEPT [328800:93378200]
:OUTPUT ACCEPT [352242:343481377]
COMMIT
I bring up the first null interface and create a route for the test network:
# ./null
Using interface null0 with address 169.254.0.1.
57: null0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc pfifo_fast
qlen 500
link/[65534]
inet 169.254.0.1/32 scope global null0
waiting for packets...
(in another window)
# ip ro add 1.2.3.0/24 dev null0 metric 10
The metric is so we can make the packets go to null1 later.
On another machine (B), I set up a route to the test network and ping it.
# ip ro add 1.2.3.0/24 via A
# ping 1.2.3.4
On machine A, I see the packets being masqueraded with the IP address of
null0:
# tcpdump -i null0 icmp
tcpdump: WARNING: arptype 65534 not supported by libpcap - falling back
to cooked socket
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on null0, link-type LINUX_SLL (Linux cooked), capture size 96
bytes
23:36:47.688396 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 4
23:36:48.688383 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 5
23:36:49.688413 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 6
23:36:50.688389 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 7
Now I bring up the second null interface and add a route with a lower
metric. Note the address assigned to the interface!
# ./null
Using interface null1 with address 169.254.1.1.
58: null1: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc pfifo_fast
qlen 500
link/[65534]
inet 169.254.1.1/32 scope global null1
waiting for packets...
(in another window)
# ip ro add 1.2.3.0/24 dev null1
The window where I run null1 now starts printing dots, null1 is
receiving packets. Now when I dump these packets:
# tcpdump -i null1 icmp
tcpdump: WARNING: arptype 65534 not supported by libpcap - falling back
to cooked socket
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on null1, link-type LINUX_SLL (Linux cooked), capture size 96
bytes
23:37:35.688593 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 52
23:37:36.688614 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 53
23:37:37.688626 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 54
23:37:38.688598 IP 169.254.0.1 > 1.2.3.4: icmp 64: echo request seq 55
Hey, that is the wrong source address! Now when I kill the null0
interface, suddenly the source address changes to the correct
(169.254.1.1) address. Also when I stop the ping and restart it, the
source address is correct.
Is this behaviour by design? Is it considered a bug or a feature? Is the
ping-stream from machine B seen as one contrack entry, and thus causing
this behaviour?
Regards,
M4
[-- Attachment #2: null.c --]
[-- Type: text/x-csrc, Size: 2308 bytes --]
#include <sys/types.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int tun_alloc(char *dev);
void usage(const char *msg);
const char* argv0;
const int debug = 1;
int main(int argc, char **argv)
{
int fd_tun;
char null_intf[260];
char scratch[1024];
int intf_no;
argv0 = argv[0];
if (argc > 1)
usage(0);
if (geteuid())
usage("Must be run by root");
strcpy(null_intf, "null%d");
if ((fd_tun = tun_alloc(null_intf)) < 0) {
perror("Could not alloc tun device");
exit(1);
}
intf_no = atoi(null_intf+4);
printf("Using interface %s with address 169.254.%d.1.\n", null_intf, intf_no);
/* Bring up the interface with a link local address */
sprintf(scratch, "/sbin/ip link set %s up", null_intf);
system(scratch);
sprintf(scratch, "/sbin/ip addr add 169.254.%d.1/32 dev %s", intf_no, null_intf);
system(scratch);
if (debug) {
sprintf(scratch, "/sbin/ip addr ls dev %s", null_intf);
system(scratch);
}
debug && puts("waiting for packets...");
while (1) {
if (read(fd_tun, scratch, sizeof(scratch))<0) {
perror("Error reading from tun device");
exit(1);
}
if (debug) {
printf(".");
fflush(stdout);
}
}
/* never get here */
close(fd_tun);
exit(0);
}
void usage(const char *msg)
{
if (msg)
printf("Error: %s\n\n", msg);
printf("Null interface, discard everything sent here.\n"
"\n"
"usage: %s <interface> <route> [<route> ...]\n", argv0);
exit(1);
}
int tun_alloc(char *dev)
{
struct ifreq ifr;
int fd, err;
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
/* return tun_alloc_old(dev); */
perror("Cannot open tun allocation device");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
if( *dev )
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
strcpy(dev, ifr.ifr_name);
return fd;
}
next reply other threads:[~2006-04-17 21:46 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-17 21:46 Martijn Lievaart [this message]
2006-04-19 10:28 ` Strange MASQUERADING behaviour, bug or feature? Amin Azez
2006-04-19 16:28 ` Martijn Lievaart
2006-04-20 8:00 ` Yasuyuki KOZAKAI
2006-04-20 8:11 ` Amin Azez
2006-04-20 10:40 ` Martijn Lievaart
[not found] ` <44476A21.7070609@ufomechanic.net>
2006-04-20 11:16 ` Martijn Lievaart
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=44440CD2.6060006@rtij.nl \
--to=m@rtij.nl \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.