[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