Use UDP without specifc port for Multicast - python

IP multicast gives you the ability to send a single packet, which is picked up by multiple interfaces if they are subscribed to that multicast. If I understand it correctly.
Now if I want to use UDP, in combination with IP multicast, I am obligated to assign a port to listen to. But now I understand that I only receive UDP packets on a multicast specifically sent to that port. But I would like to intercept all UDP packets send to a certain multicast IP address, regardless of the port and receive them at my single socket.
Is something like this possible?
Preferably accompanied by a python example, if this is possible.

This isn't possible using the BSD socket API (which is roughly the API Python exposes in its socket module) - except by creating 2 ** 16 - 1 sockets and using them to bind to all ports.
It's possible using lower-level interfaces such as the TUN/TAP system offered by Linux.

Related

How to capture martian packets without letting the linux kernel to drop them and then catching them using raw sockets

I'm trying to setup a network to simulate an Edge computing scenario with LTE. But the question here is more pertaining to IP tables and raw sockets on the server.
I have the following setup:
PC-A is the Tower, PC-C is the LTE Core, PC-B is acting as intermediary and routing data using proxy ARPs
Cell phone wants to connect to a TCP server on PC-B(IP: 172.17.1.3)
Cell phone(IP:192.172.0.2) sends packets to PC-A(IP: 172.17.1.1)
The data from PC-A(172.17.1.1) generally has to reach LTE-EPC on 172.17.1.4 which is connected via PC-B(172.17.1.2 - 172.17.1.3 with proxy ARPs). And the data comes in the form of UDP packets to PC-B(IP: 172.17.1.2)
I use NAT table and python script with raw sockets to send all of these UDP packets to a local port, do some filtering, decapsulate the GTP headers and send the TCP/IP packet to the TCP server on PC-B interface(172.17.1.3). I use the below iptables settings to do this
iptables -t nat -A PREROUTING -p udp -d 172.17.1.4 --dport 2152 -j DNAT --to-destination 172.17.1.2:7000
Until here everything works, the extracted TCP/IP packet also reaches the TCP server on 172.17.1.3. The server responds to these packets. For example, for the SYN packet from the cell phone, the server now sends out SYN, ACK. However, the server responds to the original source address 192.172.0.2.
I want to catch these response TCP/IP packets from the TCP server 172.17.1.3 to 192.172.0.2 and do some GTP encapsulation before sending them back to PC-A.
Can anyone tell me how I can use the iptables to tell the kernel to stop dropping these martian packets with destination address 192.172.0.2, but instead forward to a local ip and port, so I can read the same.
I can see the SYN, ACK responses from the server on wireshark. But I assume that these are dropped as I already tried to route it to local ip:port using a similar iptables rule from above.
Any help is much appreciated, Thank you.
It sounds like a tun/tap interface could be useful here. Here's the official Linux kernel documentation.
Both these interface types allow a program to create a virtual network interface. This is designed for tunnels and VPNs and it seems like that is exactly what you are creating.
According to the linked documentation, you may create an interface by opening /dev/net/tun (O_RDWR) and issuing this ioctl to initialize it:
struct ifreq req;
memset(&req, 0, sizeof(req));
req.ifr_flags = IFF_TUN; // or IFF_TAP
strncpy(req.ifr_name, "tunnel%d", IFNAMSIZ); // optional; leave it blank to get a default name; you don't have to have a %d
ioctl(fd, TUNSETIFF, &req); // error check omitted for demonstration
// req.ifr_name now contains the name that was actually selected
After the ioctl you have a virtual network interface in your system. You can configure IP addresses, routes, whatever.
Any time the kernel sends a packet out through your interface it will go into a queue and you'll be able to read it. Any time you write to the interface the kernel will process it as if it's a real packet that just arrived.
You will need to configure networking like it's a real interface. Set up a static route so that 192.172.0.0/16 (or whatever your subnet is) is reached through the tunnel interface. I'm not sure if Linux will let you do this without giving it an address; you might have to give it a dummy address like 192.172.255.254. Or a completely unrelated address like 1.2.3.4 and then let Linux think there's another router in front of your cellphone subnet. Or maybe it will just work without an address - not sure.
The difference between "tun" and "tap" is whether Ethernet processing happens or not (IP tunnel vs Ethernet tap). I expect tun is right for your application. If you choose tap then Linux will also use ARP and so on, and the interface will certainly need an address.
You might find it convenient to use the tunnel interface in both directions, or just one. IP packets aren't required to take the same route in both directions. This is the "correct" way to implement a tunnel, so you might find that a lot of mysterious bugs go away by using it.

Setting source address when sending UDP multicast messages

How to set the source IP address for UDP multicast packages to something else than the interface IP?
I am trying to write a small router that selectively routes UDP SSDP packages from one network to another. The plan is to do it in python, although I am flexible on that.
It seems fairly easy to route SSDP NOTIFY messages: I receive them on one interface and decide which interface to re-broadcast them on. However the protocol for M-SEARCH messages require that the source IP is set to the original source of the message as any service that chooses to respond will respond with a unicast message to the source IP and port.
Example (heavily simplified):
Network A: 192.168.10.0/24
Network B: 192.168.11.0/24
My router application runs on a multihomed computer on 192.168.10.2 and 192.168.11.2.
A client on network A with IP 192.168.10.10 sends an M-SEARCH message:
Src IP/Port: 192.168.10.10 port 40000
Dst IP/Port: 239.255.255.250 port 1900
My "router application" on 192.168.10.2 receives the packet and would like to rebroadcast it on network B. However I cannot find any method in the socket API that allows me to set the source IP address. Only to pick the source interface.
Thus the rebroadcasted packet now looks like this:
Src IP/Port: 192.168.11.2 port xxxxx
Dst IP/Port: 239.255.255.250 port 1900
And now the receiving service is unable to unicast back to the client as the original IP and port are lost.
How to set the source IP address for UDP multicast packages to something else than the interface IP?
The only way I know of is to use a RAW socket and construct the IP headers manually. Note that use of RAW sockets is typically restricted to admin users on most platforms.
However I cannot find any method in the socket API that allows me to set the source IP address.
Because there isn't one.
And now the receiving service is unable to unicast back to the client as the original IP and port are lost.
Can't you just have your router remember the original source when it receives the M-SEARCH request, and when it receives the unicast reply then forward it to the original requester? That is how most routers usually work.

Facing problems with socket programming for video streaming

I have two transceivers which support serial communication (UART). I am using socket programming on python for generating UDP data grams. Is there any way to port these datagrams to the serial port on the transmitter and then back from serial port to UDP datagram on the receiver. I am new to this so some examples would be highly appreciated.
Use the point-to-point protocol (PPP). That's what it was designed to do.
If you're running on Linux or some other UNIX-like operating system, you'll use pppd on both ends of the serial connection.
Most of the articles on setting this kind of thing up date back to the dial-up internet days. Here's an example: http://www.tldp.org/HOWTO/PPP-HOWTO/
Essentially, PPP creates interfaces with IP addresses on both ends of your serial connection. Send packets to the remote interface's IP address, and it tunnels them over the serial link.

Multiple TCP connections in python

I'm trying to write a server for a chat program. I want the server to have a tcp connection with every chat user. Is there way for the server to have multiple tcp connections at the same time without creating a socket for every connection? And if yes, how?
No. Unlike UDP sockets, TCP sockets work are connection-oriented. Whatever data is written into a socket, "magically" appears to come out of the socket at the other end as a stream of data. For that, both sockets maintain a virtual connection, a state. Among other things, the state defines both endpoints of the conntection - IP and port numbers of both sockets. So a single TCP socket can only talk to a single TCP socket at the other end.
UDP sockets on the other hand operate on a per-packet basis (connectionless), allowing you to send a receive packets to/from any destination using the same socket. However, UDP does not guarantee reliability and in-order delivery.
Btw, your question has nothing to do with python. All sockets (except raw sockets) are operating system sockets that work in the same way in all languages.

Difference Between Socket Types

Yes, I did already try to find information on this.
The Python socket documentation has this list of what I believe are protocols:
SO_*
socket.SOMAXCONN
MSG_*
SOL_*
IPPROTO_*
IPPORT_*
INADDR_*
IP_*
IPV6_*
EAI_*
AI_*
NI_*
TCP_*
What exactly do they do? Let's say I used
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
What does this do? I understand it's a raw socket, but does the IPPROTO_IP mean I have to construct everything? (i.e. the IP header down to the TCP to the data?)
The Python documentation says I can find information on the above in the Unix documentation on sockets, but I couldn't find the document. Anyone know where it is?
There are a lot of Linux manual pages describing socket:
SOCKET
IP
TCP
UDP
UNIX
In general, we use these arguments for socket:
Address family: AF_INET for internet domain address family, AF_UNIX for UNIX domain address family.
Socket type: SOCK_STREAM for TCP, SOCK_DGRAM for UDP. Of course you can use SOCK_RAW for directly access IP protocol.
Protocol: when using TCP or UDP, leave it to 0 is just fine; when using RAW, you can specify protocol to 0, IPPROTO_TCP for TCP sockets, IPPROTO_UDP for UDP sockets.
And, SO_ means "socket option", SOL_ means "socket option level", which are used to set socket options through setsockopt (also mentioned in SOCKET).
In fact, you can find more pages at the bottom of these pages in the SEE ALSO section. Note that the page of 2 or 3 is a concrete system call or library function, pages of 7 is what you need.

Categories

Resources