Hello,
I've been struggling with this problem for months, and my limited networking knowledge doesn't allow me to progress further, so here I am asking for an advice.
I have two subnets, 192.168.1.x and 192.168.2.x. On 192.168.1.x I have a client PC running an application I don't have sources of, and on 192.168.2.x runs a server of the same software. In order to discover other servers, the client sends a broadcast on the local network that obviously won't traverse the subnet. But since I know where the server is, I would like to somehow "transform" such broadcast in a normal UDP packet with the destination address of that server. Is this something I can even do with iptables? If so, could someone give me some directions in order to write a proper rule?
Thank you so much!
There are some options depending on your routing configuration:
- Arrange the client and the server to the same subnet:
- If the server has a free NIC, connect it to the client's subnet.
- Connect the client directly to the server with L3 IP/VPN tunnel.
- Connect the client to the router's other subnet with L2 IP/VPN tunnel.
- Try to use SNAT/DNAT rules to modify the traffic source/destination.
1 Like
Since I put the server in the other subnet in order to isolate it from the rest of the network (it is publicly exposed on Internet, with also people accessing it via TeamViewer) I would love to keep it there. So I was looking at a SNAT/DNAT rule but I'm really struggling with it. This is what I came to:
iptables -t nat -A zone_lan_prerouting -p udp -s 192.168.1.0/24 -d 255.255.255.255 -m udp --dport 10307 -j DNAT --to-destination 192.168.2.36:10307 -m comment --comment "Broadcast Traverse Test"
The client in the "lan" zone, and the server is at 192.168.2.36. But apparently the packet never reaches the server (I'm listening with Wireshark on the server).
You may also need to modify TTL and add a SNAT rule or masquerading to hide the source.
Note however that sending unicast traffic will not work if the server only expects broadcasts.
So, if the proposed modifications do not help, consider other options as well.
1 Like
I'm pretty sure it should work because the same server also replies to other unicast packets coming from other clients on Internet.
Yeah, I think I'll look at SNAT as well (although the source header contains the correct IP Address) but first I'd just want to make my unicast packet reach the server...
1 Like
Keep in mind that initial packets for the service discovery may be processed differently from direct connections, that's why it is best to capture and carefully analyze those broadcast requests.
1 Like
It could be, of course... But I guess I have to get that packet to the server in the first place, anyway 
Ok, I have an update: through ebtables
I managed to rewrite the dest MAC address so that it doesn't look like a broadcast anymore, and in conjunction with the above mentioned iptables now the packet reaches the server:
ebtables -t nat -A PREROUTING -p ip --ip-protocol udp -d ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff --ip-destination-port 10307 -j dnat --to-destination 9c:c9:eb:15:dd:ce
Not only: the server actually replies, but the packet is not sent back to the client. Now, it could be because as I said all traffic should be blocked from the server zone to the client zone; nonetheless, because the traffic is allowed the other way around (i.e. from the client zone to the server zone), why I can successfully establish a connection from the client to the server, but not from the server to the client? I mean, traffic is allowed only client->server, so any UDP packet coming from the server should be dropped regardless of a previously successful connection, isn't it?
Probably connection tracking is not implemented for your protocol.
Responses not matching the related/established state need to be explicitly allowed.
Uhm... yeah, I thought somerthing similar. But apparently conntrack
is matching the traffic both ways:
[NEW] udp 17 60 src=192.168.1.227 dst=255.255.255.255 sport=53917 dport=10308 [UNREPLIED] src=192.168.2.36 dst=192.168.1.227 sport=10308 dport=53917
[UPDATE] udp 17 86400 src=192.168.1.227 dst=255.255.255.255 sport=53917 dport=10308 src=192.168.2.36 dst=192.168.1.227 sport=10308 dport=53917 [OFFLOAD]
[NEW] udp 17 60 src=192.168.1.227 dst=255.255.255.255 sport=53917 dport=10310 [UNREPLIED] src=192.168.2.36 dst=192.168.1.227 sport=10310 dport=53917
[UPDATE] udp 17 86399 src=192.168.1.227 dst=255.255.255.255 sport=53917 dport=10310 src=192.168.2.36 dst=192.168.1.227 sport=10310 dport=53917 [OFFLOAD]
I just cannot understand that OFFLOAD
...
Well... it doesn't seem to be of any interest for my case.
I think I'm so close: I can see the return packet leaving the server, and logged in the router... but somehow it cannot reach the client, and I don't know where to look :\
A permissive firewall rule for initial responses is still necessary.
I'm afraid this kind of communication does not expect a firewall in the middle.
Well, that should be covered by
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED /* !fw3 */
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED /* !fw3 */
FLOWOFFLOAD all -- anywhere anywhere /* !fw3: Traffic offloading */ ctstate RELATED,ESTABLISHED FLOWOFFLOAD hw
isn't it?
EDIT: I also disabled offloading (unneeded noise in my head for now) and allowed all forwarding between the two zones, both directions, for the sake of testing, and still no joy 
That is only relevant for related/established connections for unicast traffic.
The initial service discovery broadcast queries cannot be used for connection tracking.
So, the following unicast replies must be allowed explicitly.
But the reply seems to be a unicast reply from server to client, isn't that so? Because it's just the reply that is somehow dropped...
Connection tracking cannot associate unicasts with broadcasts, so netfilter considers unicasts as starting packets and drops them, since you have prohibited forwarding from the server to the clients.
Well, my understanding was that conntrack actually manages to correlate the two connections: now that I disabled offloading, I get:
[NEW] udp 17 60 src=192.168.1.227 dst=255.255.255.255 sport=65137 dport=10308 [UNREPLIED] src=192.168.2.36 dst=192.168.1.227 sport=10308 dport=65137
[UPDATE] udp 17 60 src=192.168.1.227 dst=255.255.255.255 sport=65137 dport=10308 src=192.168.2.36 dst=192.168.1.227 sport=10308 dport=65137
[UPDATE] udp 17 60 src=192.168.1.227 dst=255.255.255.255 sport=65137 dport=10308 src=192.168.2.36 dst=192.168.1.227 sport=10308 dport=65137 [ASSURED]
And anyway, as I said, I also opened up forwarding for the whole zones but still can't see that packet going back...
Another, unfortuately small, progress:
On the OUTPUT
chain I have ebtables
logging these entries for the response:
IN= OUT=wlan0 MAC source = 9c:c9:eb:15:dd:ce MAC dest = 50:2f:9b:2a:ba:9d proto = 0x0800 IP SRC=255.255.255.255 IP DST=192.168.1.227, IP tos=0x00, IP proto=17 SPT=10308 DPT=51719
IN= OUT=wlan0 MAC source = 9c:c9:eb:15:dd:ce MAC dest = 50:2f:9b:2a:ba:9d proto = 0x0800 IP SRC=255.255.255.255 IP DST=192.168.1.227, IP tos=0x00, IP proto=17 SPT=10308 DPT=51719
Am I right assuming conntrack
is playing a role here by routing the packet from the wrong source address? I would expect to have 192.16.2.36
as the SRC IP here, and not having this packet in the OUTPUT
chain at all, but rather in the FORWARD
chain...
Can you just add a vlan interface to the server and have it participate in the subnet of interest? You could filter the packets by bridge filtering so it only sees /sends the packets it needs.