Linux socket UDP server - exchanging messages between 2 servers on 2 machines - linux

I am working on a small linux socket project. The goal is to have multiple servers (ie. 1,2,3,4,5) that listen for send get and ACK packets from each of their respective clients. I am currently attempting to implement a routing table protocol whereby 2 servers (A, B) exchange their routing tables (vectors containing respective clients, server name, and number of hops). The issue I am having is with binding a socket to B's external address from A and vice-versa. From what I have read you do not bind to anything other than a local address except in certain cases. What I am wondering is how do I simply fire off a UDP packet from one server to another knowing the (static) IP address of each server?

What I am wondering is how do I simply fire off a UDP packet from one
server to another knowing the (static) IP address of each server?
The short answer is, you can't. At least on the Internet proper, only unicast is widely supported, which means that in order to send a UDP packet to another machine, you'll need to know its IP address (somehow).
The longer answer is: The first thing you often need to do is discover the target machines' IP addresses. That might be a matter of having the user manually enter a list of IP addresses, or if the target machines are on the same LAN, you can program a mechanism for auto-discovering them by having your program send out a broadcast or multicast UDP query packet. Make sure any instances of your program running on the same LAN receive that packet and respond to it by sending back a response UDP packet (the responses can be sent by by unicast or multicast or broadcast, your choice), and then your query-originating computer can know from the responses it receives which other IP addresses your program is presently also running on.
Note that a lot of computers and network devices run firewalls that reject incoming UDP packets by default, so if you packets don't seem to be getting through that is a likely reason why.

Related

Designing a DSR load balancer

I want to build a DSR load balancer for an application I am writing. I wont go into the application because it is irrelevant for this discussion. My goal is to create a simple load balancer that does direct server response for TCP packets. The idea is to receive all packets at the load balancer, then using something like round robin, select a server from a list of available servers which are defined in some config file. The next step would be to alter the packer received and change the destination ip to be equal to the chosen backend server. Finally, the packet will be sent over to the backend server using normal system calls for sending packets. Theoretically the backend server should receive the packet, and send one back to the original requester, and then the requester can communicate directly with the backend server rather than going through the load balancer.
I am concerned that this design will not work as I expect it to. The main question is, what happens when computer A send a packet to IP Y, but receives a packet back in the same TCP stream from a computer at IP X? Will it continue to send packets to IP Y? Or will it switch over to IP X?
So it turns out this is possible, but only halfway so, and I will explain what I mean by this. I have three processes, one which is netcat, used to initiate an tcp request, a second process, the dsr-lb, which receives packets on a certain port, changes the destination ip to a backend server(passed in via command line arg), and forwards it off using raw sockets, and a third process which is a basic echo server. I got this working on a local setup. The local setup consists of netcat running on my desktop, and dsr-lb and echo servers running on two different linux VMs on the desktop as well. The path of the packets was like this:
nc -> dsr-lb -> echo -> nc
When I said it only half works, what I meant was that outgoing traffic has to always go through the dsr-lb, but returning traffic can go directly to the client. The client does not send further traffic directly to the backend server, but still goes through the dsr-lb. This makes sense since the client opened a socket to the dsr-lb ip, and internally still remembers this ip, regardless of where the packet came from.
The comment saying "if its from a different IP, it's not the same stream. tcp is connection-based" is incorrect. I read through the linux source code, specifically the receive tcp packet portion, and it turns out that linux uses source ip, source port, destination ip, and destination port to calculate a hash which is uses to find the socket that should receive the traffic. However, if no such socket matches the hash, it tries again using only the destination ip and destination port and that is how this "magic" works. I have no idea if this would work on a windows machine though.
One caveat to this answer is that I also spun up two remote VMs and tried the same experiment, and it did not work. I am guessing it worked while all the machines were on the same switch, but there might be a little more work to do to get it to work if it goes through different routers. I am still trying to figure this out, but from using tcpdump to analyze the traffic, for some reason the dsr-lb is forwarding to the wrong port on the echo server. I am not sure if something is corrupted, or if the checksum is wrong after changing the destination ip and some router along the way is dropping it or changing it somehow(I suspect this might be the case) but hopefully I can get it working over an actual network.
The theory should still hold though. The IP layer is basically a packet forwarding layer and routers should not care about the contents of the packets, they should just forward packets based on their routing tables, so changing the destination of the packet while leaving the source the same should result in the source receiving any answer. The fact that the linux kernel ultimately resolves packets to sockets just using destination ip and port means the only real roadblock to this working does not really exist.
Also, if anyone is wondering why bother doing this, it may be useful for a loadbalancer in front of websocket servers. Its not as great as a direct connection from client to websocket server, but it is better than a loadbalancer that handles both requests and responses, which makes it more scalable, and more able to run on less resources.

How to receive multicast packets hitting NIC without actually sending IGMP request?

I have 2 Ubuntu 16.04 machines "A" and "B" in my local network. "A" periodically sends multicast UDP packet targeted at 225.0.0.37.
On system "B" I can verify through wireshark that those packets are hitting my NIC. I want to write a C program which creates a SOCK_DGRAM socket and listens to these packets without sending IGMP join packet in the network. If I write such a program the kernel doesn't allow these packets to reach my application. They get filtered on IP layer 3 (its my guess).
Is there a way of achieving this? I don't want any IGMP packet leaving my system but still want to capture the UDP traffic. One option that I know works is to use SOCK_RAW, but i want to achieve this from SOCK_DGRAM only.
I know that os keeps igmp subscription entries in /proc/net/igmp and /proc/net/dev_mcast. And these entries are created only if I send an IP_ADD_MEMBERSHIP request from an interface from a program. And these entries get cleared as soon as the program terminates. Maybe there is a way to fool kernel to create this entry.

How Firewall bocks ports

When we say firewall has blocked port 28 doest it mean that a firewall process running on a computer scans every packet it receives and if it finds a packet containing port 28 (since packet contains port information) it will not pass that packet on to particular service listening on port 28
Firewalls examine every packet coming in (and often going out). If the firewall rules dictate that the packet should be blocked, then it is not passed on. What "passed on" means depends on the context. On an end-point machine, the packet is not sent to the application handling the network traffic. On a router or firewall appliance, the packet is not sent on the output link.
The firewall can completely drop the packet, or if it is TCP connection packet it can ACK the packet then send a reset:
Rational for dropping packets:
If you run no internet facing services, dropping packets instead of rejecting them (RST,ACK) allows you to make your machine to appear to be offline to attackers (as long as you block pings etc). If you run services on uncommon (high range) ports, dropping packets on closed ports can make an attacker overlook you as they may not scan the higher ranges. However, if you run services on common ports and most ports drop packets while these ports reject them, you are actually giving information about what services your system runs. So drop on all ports or don't bother. Link

Resolve IP next hop with socket programming on Linux

Working with Linux.
Given a specific destination IP address, I need to populate the ARP cache with its next hop MAC address and interface.
Other mechanism in my software project will take this MAC address and push it to an FPGA.
If I open a TCP connection to the address it will be resolved and TCP handshake packets are sent. If I open a UDP socket and 'connect' it to the address it will not be resolved. If I send a single packet over the connected UDP socket it is resolved.
arp(7) documentation explains this: "... Requests are sent only when there is data queued for sending".
I can't call the 'arp' utility directly.
My question: is there a way to convince the system to populate an address by sending ARP in the background without the need for actually sending a packet?
I hope for some ioctl or setsockopt.
I prefer a generic solution that will also work for IPv6 neighbor resolution.
Thanks,
Gur

howto make locally terminated tcp connections go through prerouting and postrouting?

I am developing an application that filters and mangles packets using netfilter queue's. It's rather complicated and needs to perform well so I would like to automate some rigorous testing. To do this I need to be to be able to route some TCP connections through my system, however, I don't want to have to rely on two other machines to act as client and server. I would prefer to run a local client that sends data and a local server that checks the mangled result.
The problem is that my application needs to intercept packets at the PREROUTING stage and so packets generated by the local client can't just be routed to the loopback interface.
So I need some way to inject packets before the prerouting stage and intercept them back after postrouting. If I could somehow use stream sockets to send and receive the data that would be great!
The most straightforward way I can think of doing this is to use a tun device. The tun device allows you to inject packets from userspace that appear to arrive through the tun interface. You could either write code to create and manipulate the tun interface yourself, or you can make use of an application like OpenVPN that already does this. With OpenVPN it would be easy: no special raw sockets or anything: you just send it IP packets encapsulated in UDP and it will make them arrive through a tun interface.
I've been thinking a bit about this and using the tun devices my client and server test applications should be able to use plain linux sockets. I will explain how this can work by describing the path of a packet sent by the test client.
Prerequisites:
a) Two tun devices each providing access to a distinct subnetwork
b) routing table was set up to route traffic to the correct tun device
1) the client sends a packet to an address in the tun1 subnetwork
2) the app attached to tun1 (tun1app) will translate the dst address of the packet to an address in tun2 subnetwork and the source address to an address in the tun1 subnetwork different from the address of the tun1 interface
3) tun1app will send the modified packet back out
4) after routing tun2app will receive the packet and translate the destination address to the tun2 interface and the source address to an address in the tun2 network different from the interface address
5) tun2app will send it back out and the server will receive the packet assuming the destination port is the one the server is listening on
Packets from the server will follow the inverse path.
This seems like the core idea of a very useful tool. Does anyone know of a tool that is able to do this?
All connections from-and-to localhost itself do go over PREROUTING and POSTROUTING. Whoever tells something else is mistaken. (You can verify that with ip6tables -t raw -I OUTPUT -j TRACE, and you will see that it passes through OUTPUT-POSTROUTING-PREROUTING-INPUT when, for example, you ping6 ::1 yourself.)

Resources