Hello, While I can see example of using udp on tproxy2 onto the redirect-udp-recv.c file, I can't find equivalent on tproxy4. For getting the original destination IP, I just use setsockopt IP_PKTINFO: setsockopt(sd, SOL_IP, IP_PKTINFO , &flags, sizeof(flags)); But I don't know how to get the original destination port: a) I manually defined IP_RECVORIGADDRS to be 11273 as I find on tproxy2: setsockopt(sd, SOL_IP, IP_RECVORIGADDRS , &flags, sizeof(flags)); but the setsockopt failed. b) the getsockname give me the server listening port. Here are my iptables\ip route redirection lines: ${iptables} -t mangle -N DIVERT ${iptables} -t mangle -A PREROUTING -p udp -m socket -j DIVERT ${iptables} -t mangle -A DIVERT -j MARK --set-mark 1 ${iptables} -t mangle -A DIVERT -j ACCEPT ${iptables} -t mangle -A PREROUTING -p udp --dport 1500 -j TPROXY --tproxy-mark 1 --on-port 3127 ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100 What is missed? Best, Moshe
Hi, On sze, nov 12, 2008 at 11:40:30 +0000, Andrey Luzgin wrote:
Hello,
While I can see example of using udp on tproxy2 onto the redirect-udp-recv.c file, I can't find equivalent on tproxy4.
For getting the original destination IP, I just use setsockopt IP_PKTINFO: setsockopt(sd, SOL_IP, IP_PKTINFO , &flags, sizeof(flags));
But I don't know how to get the original destination port:
a) I manually defined IP_RECVORIGADDRS to be 11273 as I find on tproxy2: setsockopt(sd, SOL_IP, IP_RECVORIGADDRS , &flags, sizeof(flags)); but the setsockopt failed.
b) the getsockname give me the server listening port.
Since tproxy 4 (unlike tproxy 2) doesn't modify the incoming packets in any way you should be able to get the correct destination address by simply calling recvfrom() and using the source address returned by the kernel. -- KOVACS Krisztian
On Wed, 2008-11-12 at 19:59 +0100, KOVACS Krisztian wrote:
Hi,
On sze, nov 12, 2008 at 11:40:30 +0000, Andrey Luzgin wrote:
Hello,
While I can see example of using udp on tproxy2 onto the redirect-udp-recv.c file, I can't find equivalent on tproxy4.
For getting the original destination IP, I just use setsockopt IP_PKTINFO: setsockopt(sd, SOL_IP, IP_PKTINFO , &flags, sizeof(flags));
But I don't know how to get the original destination port:
a) I manually defined IP_RECVORIGADDRS to be 11273 as I find on tproxy2: setsockopt(sd, SOL_IP, IP_RECVORIGADDRS , &flags, sizeof(flags)); but the setsockopt failed.
b) the getsockname give me the server listening port.
Since tproxy 4 (unlike tproxy 2) doesn't modify the incoming packets in any way you should be able to get the correct destination address by simply calling recvfrom() and using the source address returned by the kernel.
This is not true, recvfrom() returns the client address and does not return the original destination. There was a hack in 2.2 kernels, that it could return the targeted address in the 2nd half of the "struct sockaddr_in" structure. But that hack was crude. I can only see two options to proceed with full udp proxying: accept() support for UDP, or a recvmsg() ancillary data (IP_RECVORIGADDRS) as above. I'll see whether I can come up with a patch for the latter. In Zorp we're using accept() for UDP sockets, but I doubt it could be integrated to mainline, the other option is doable, although potentially racy. -- Bazsi
On Wed, 2008-11-12 at 11:40 +0000, Andrey Luzgin wrote:
Hello,
While I can see example of using udp on tproxy2 onto the redirect-udp-recv.c file, I can't find equivalent on tproxy4.
For getting the original destination IP, I just use setsockopt IP_PKTINFO: setsockopt(sd, SOL_IP, IP_PKTINFO , &flags, sizeof(flags));
But I don't know how to get the original destination port:
a) I manually defined IP_RECVORIGADDRS to be 11273 as I find on tproxy2: setsockopt(sd, SOL_IP, IP_RECVORIGADDRS , &flags, sizeof(flags)); but the setsockopt failed.
b) the getsockname give me the server listening port.
Here are my iptables\ip route redirection lines: ${iptables} -t mangle -N DIVERT ${iptables} -t mangle -A PREROUTING -p udp -m socket -j DIVERT ${iptables} -t mangle -A DIVERT -j MARK --set-mark 1 ${iptables} -t mangle -A DIVERT -j ACCEPT ${iptables} -t mangle -A PREROUTING -p udp --dport 1500 -j TPROXY --tproxy-mark 1 --on-port 3127
ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100
Well, for supporting UDP with tproxy4 we use a different approach: udp_accept(), you can find it in the BalaBit kernel patch tree at http://www.balabit.com/downloads/files/kernel-patches/ The way udp_accept() works is as follows: * the userspace proxy opens a "listening" udp socket, binds it to the listening address, performs no connect() calls * tproxy redirects packets to this socket just like in the case for TCP * whenever the socket becomes readable from the userspace proxy, accept() is invoked on the UDP socket, this accept() is implemented by the patch mentioned above * in kernel space: the first packet is consulted from the socket buffer of the listening socket * the kernel opens a new UDP socket, just like the accept() call for TCP does * this new UDP socket is bound this way: * local address is the same as the destination address of the incoming packet * destination address is the same as the source address of the incoming packet * the socket buffer of the listening socket is traversed, and each packet having the same IP addresses as the first packet is moved to the newly opened socket; this traversal is happening in an atomic context, thus no new packets can arrive * a reference to the newly opened socket is returned to userspace * when a new packet comes in, the socket lookup will prefer the completely bound socket over the listening socket Since at the end of the accept() call you get a completely bound socket, you can simply call getsockname() to query the target address, just like with TCP. Hope this helps. PS: I was talking to Patrick McHardy whether to send the udp_accept() patch for kernel inclusion, he said it might be worth trying, however he was not completely sure it'd be integrated. So I didn't push it so far. -- Bazsi
participants (3)
-
Andrey Luzgin
-
Balazs Scheidler
-
KOVACS Krisztian