[tproxy] NAT Reservation
KOVACS Krisztian
hidden@balabit.hu
Mon, 08 Nov 2004 10:12:42 +0100
Hi,
2004-11-08, h keltezéssel 03:28-kor Tim Burress ezt írta:
> We're using TPROXY 2.0.0 for 2.4.27 and are running
> into a strange issue which seems related to NAT
> reservation. As usual, we have a client TCP connection
> coming in from a given <saddr,sport> going to a
> particular <daddr,dport>. Netfilter rules REDIRECT
> this to our proxy code, which then uses TPROXY to
> connect out to <daddr,dport> using <saddr,sport> as
> the apparent source.
>
> We use the same operation sequence that appears in the
> test directory: first bind the socket to a local
> address, then do a TPROXY ASSIGN assigning
> <saddr,sport> to the socket, then TPROXY FLAGS to set
> ITP_CONNECT|ITP_ONCE, and then the actual connect().
>
> With earlier versions of TPROXY (though I can't
> guarantee that kernel options haven't changed) this
> worked fine. Now, though, we see two problems. First,
> on when we make the call to ASSIGN, we get an error:
>
> IP_TPROXY: ip_tproxy_nat_reserve proto 6 foreign
> 10.0.0.2:32772 peer 0.0.0.0:0
> IP_TPROXY: IP_TPROXY_ASSIGN cannot register NAT
> reservation 0200000a:0480
>
> Apparently the NAT reservation is failing because when
> the initial TCP connection came in, conntrack set up a
> record expecting a reply to <saddr,sport>. The only
> way I could see to get around this was to set
> SO_REUSEADDR on the socket before the call to ASSIGN.
>
> However the second problem is that, if I do this, I
> get an error in the FLAGS call:
>
> IP_TPROXY: ip_tproxy_nat_reserve proto 6 foreign
> 10.0.0.2:32775 peer 0.0.0.0:0
> IP_TPROXY: IP_TPROXY_FLAGS sr c660bf9c: failed to
> register NAT reservation
>
> I was able to work around these problems by first
> setting SO_REUSEADDR on the socket before the ASSIGN
> than clearing it before the FLAGS call, but that
> doesn't seem ideal. Is this how it's supposed to be
> done, or do I just have some basic misunderstanding
> about how TPROXY should be used? I have to admit I'm
> not clear on the purpose of NAT reservations.
Before using TPROXY_FLAGS you should specify the other endpoint of the
new connection using TPROXY_CONNECT. Try something like this (augmented
foreign-tcp-connect.c, completely untested):
54 /* assign foreign address */
55 itp.op = TPROXY_ASSIGN;
56 inet_aton(FOREIGN_IP, (struct in_addr *) &itp.v.addr.faddr);
57 itp.v.addr.fport = htons(2000);
58
59 if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1)
60 {
61 perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_ASSIGN)");
62 return -1;
63 }
64
65 /* specify peer endpoint: the same address we will pass to connect() */
66 itp.op = TPROXY_CONNECT;
67 inet_aton(DEST_IP, (struct in_addr *) &itp.v.addr.faddr);
68 itp.v.addr.fport = htons(80);
69 if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1)
70 {
71 perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_CONNECT)");
72 return -1;
73 }
74
75 /* set connect flag on socket */
76 itp.op = TPROXY_FLAGS;
77 itp.v.flags = ITP_CONNECT | ITP_ONCE;
78 if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1)
79 {
80 perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_FLAGS)");
81 return -1;
82 }
83
84 /* connect */
85 inet_aton(DEST_IP, &sin.sin_addr);
86 sin.sin_port = htons(80);
87 if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) == -1)
88 {
89 perror("connect");
90 return -1;
91 }
--
Regards,
Krisztian KOVACS