Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

On a Linux box, I have a program that, among other things, sends UDP packets to a "private" IP address. I want to rewrite these packets to have a different destination IP address, without affecting the source/destination UDP ports, and without modifying the program itself.

  • Client sends: 192.168.1:138234.56.138 (with 192.168.1 inside UDP data)

  • Server receives: 12.3.45:138234.5.6:138 (with 192.168.1 inside UDP data)

  • Server sends reply: 234.5.6:138192.168.1:138

  • I want it to be: 234.5.6:13812.3.45:138


The only thing that comes to mind is iptables -t nat -I OUTPUT --dest 192.168.1.0/24 -j DNAT --to-dest <real-address>, but while it does adjust the destination IP address, it also changes the UDP source port, so the packets get rejected by the receiver.

  • After DNAT: 234.5.6:112.3.45:138 – source port changed, router rejects

Background: Said program is Samba 4, which receives NetBIOS datagrams from a client running behind a NAT. The incoming datagrams have the client's "private" IP address in their NetBIOS header, and Samba always replies to that "private" address", instead of using the source address:port of the UDP packet.

  • (client 192.168.1) ⇆ (192.168.254 router 12.3.45) ⇆ internet ⇆ (234.5.6 server)

Any ideas? (If it's impossible, I'll just fire up a VPN, but it would be interesting to make this work.)

share|improve this question
add comment

1 Answer

Finding a solution here is terribly complicated as so much depends on your entire setup and requirements. The first solution that jumps to mind is to add another iptables rule to "fix" the source port. Combined with your first idea you could put:

iptables -t nat -I OUTPUT      --dest 192.168.1.0/24 \
        -p udp --dport 138 -j DNAT --to-dest <real-address>

iptables -t nat -A POSTROUTING --dest <real-address> \
        -p udp --dport 138 -j SNAT --to-source <this-boxes-address>:138

This should solve the immediate problem. But I consider it ugly as it ties IP-addresses to a service much tighter than those should be and if <real-address> is dynamically assigned your configuration will break every now and then. A VPN is probably the quickest stable solution you can have.

Nasty thoughts

You could have an iptables INPUT rule that reacts to incoming NetBIOS requests to your SMB over the internet by triggering three to four things:

  1. starting two netcat processes back to back (means: nc -l ... | nc ...), one listening on an arbitrary port, the other one providing a UDP stream to :138 with source port 138
  2. adding a REDIRECT rule that catches samba's outgoing packets to the IP-address mentioned in the triggering NetBIOS message and redirects them to the listening port of the just created listening nc process (stay with me here!)
  3. a SNAT rule as above for each client facing nc process
  4. sacrifice a chicken

The three problems you then have to solve are

  1. have only one such construct for each client (straight forward check if there already is a nc process for the remote end you want to create)
  2. extracting the IP-address from the incoming NetBIOS message (hacky but still straight forward)
  3. clean up not required nc processes and the firewall (heuristical approach only, I think.)

If you pick a timeout for the UDP-stream-cleanup that is longer than the NetBIOS messages interval, you should be fine. I'd suggest about 3*NetBIOS interval to allow for some NetBIOS messages to get lost.

You had to ask :-)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.