How to bind socket to a specific network interface and to any ports and any IP on that interface - sockets

I have a hardware attached to my RPI board running Linux distro. This hardware & its associated Host stack has created a network interface called wpan0 and assigned some IPV6 addresses to it (I am able to ping the IPV6 address from a remote device in the same network)
Now, I want to enable data communication to this interface to any IPV6 IP assigned to the interface. How do I create and bind a socket to this interface? Also, I want to listen to any ports on this interface. How to achieve this?

How you create a socket depends on the language you use (you didn't specify), but when you want to bind a socket to ANY interface the IPv4 way is to listen to IP 0.0.0.0, the IPv6 equivalent is ::/0, that means all zeros/0 bits CIDR mask.
Redirecting all ports to one is less of a code issue and requires some hands on with IPTables and Prerouting (you can write some code that appends that to your conf file though), here is an example:
https://serverfault.com/questions/616535/iptables-destination-ip-and-port

Related

How to intercept IP packets going to the kernel Linux

I need to create a TCP session "manually", without using the connect() function. I have tried to use RAW sockets. But in this case, I only get copies of the incoming IP packets. The original incoming packets slip through to the kernel and it generates an ACK response packet that damages my protocol.
Next, variant 2, I can write a virtual eth interface driver (kernel module) and route incoming traffic to it using iptables. But there is a patched non-original (non vanila) kernel on the machine. Normal linking of the module with the kernel is not possible.
Variant 3. I also tried not to assign an IP address to the NIC interface. In this case, the network TCP/IP layer module in the kernel is not activated and it is possible to generate and receive arbitrary IP packets on the link (ethernet) layer using the PF_PACKET socket domain type in the socket() function. But at this time, any other applications using the TCP/IP protocol can’t work.
How can this problem be solved in other ways?
It would be nice if it were possible to intercept packets going from the network interface to the kernel, that is, intercept the SKBuf buffer. But I don't know how to realize it.
Apparently you are trying to create a tunnel. Instead of trying to hijack an existing interface, the proper way to create a tunnel is to create a new interface, using a kernel module or TUN/TAP. However, tunnels are normally intended to receive traffic generated on the machine which runs the tunnel software, or at least routed through it. That means you will also have to set up the kernel to route the traffic to your tunnel.
You can create a new interface as a TUN/TAP interface. It is like a virtual ethernet driver except you don't need to write a new kernel module. It is designed for tunnels (hence the name).
The difference between TUN and TAP is that a TUN interface is an IP interface that receives IP packets from the kernel's IP routing system, and a TAP interface receives Ethernet packets (which may contain IP packets) so it can alternatively be part of a bridge (a virtual Ethernet switch - which only looks at the Ethernet header, not the IP header).
I think for your scenario, you will find it easiest to create a TAP interface, then create a bridge (virtual Ethernet switch) between the TAP interface, and the interface which the other host is connected to. Neither one needs an IP address - the kernel will happily pass Ethernet-layer traffic without attempting to process the IP information in the packet. Your tunnel software can then emulate a host - or tunnel to an actual host - or whatever you want it to do.
Or in visual form:
If you want the host to also be able to talk to the machine running the tunnel software - without going through the tunnel software - then you may choose to put an IP address on the bridge.

Can I bind a client socket to an ip not belongs to any interfaces?

For a client socket, I can use bind() to bind it to a specific source Ip address to select a specific interface. Or I can use connect() directly then it will pick the source ip based on routing table.
I wonder can I bind a client socket to an ip not belongs to any interfaces ? E.g.: I have two interfaces:
eth0 : ip0
eth1 : ip1
(1) If I bind the client socket to ip2. Is this feasible ?
(2) If (1) is feasible, assuming client socket sent packets thru eth0. Then I configure the iptables in this client host, to forward all incoming packets to ip0 (eth0). In this case, if there are packets sent back from server side with destination ip address is ip2 (assuming this packet will reach my client host). Will my client socket receive the packet ?
Thanks in advance.
I don't really understand your question, but here goes:
For client sockets, you typically want the the OS and its routing table to pick the best interface for you using any available port. In which case, you bind to INADDR_ANY (0) and port 0. Or don't explicitly call bind at at all. Just call connect() and it will do the right thing.
If you need the client connection to occur through a specific interface, then bind the socket to a specific IP address. And then the OS will attempt to use that interface for the subsequent connect call and all traffic after that.
Attempting to bind the socket to an IP that doesn't belong to a local interface is surely going to result in an error.
Not sure what you mean about the iptables stuff. Sounds dicey.
Please have a look at:
https://www.rsyslog.com/doc/v8-stable/configuration/modules/omfwd.html#ipfreebind
MAN:
https://man7.org/linux/man-pages/man7/ip.7.html
IP_FREEBIND (since Linux 2.4)
If enabled, this boolean option allows binding to an IP
address that is nonlocal or does not (yet) exist. This
permits listening on a socket, without requiring the
underlying network interface or the specified dynamic IP
address to be up at the time that the application is
trying to bind to it. This option is the per-socket
equivalent of the ip_nonlocal_bind /proc interface
described below.

What does it mean to bind() a socket to any address other than localhost?

I don't understand what it means to bind a socket to any address other than 127.0.0.1 (or ::1, etc.).
Am I not -- by definition -- binding the socket to a port on my own machine.. which is localhost?
What sense does it make to bind or listen to another machine or IP address's port?
Conceptually, it just doesn't make sense to me!
(This has proven surprisingly hard to Google... possibly because I'm not Googling the right terms.)
Binding of a socket is done to address and port in order to receive data on this socket (most cases) or to use this address/port as the source of the data when sending data (for example used with data connections in FTP server).
Usually there are several interfaces on a specific machine, i.e. the pseudo-interface loopback where the machine can reach itself, ethernet, WLAN, VPN... . Each of these interfaces can have multiple IP addresses assigned. For example, loopback usually has 127.0.0.1 and with IPv6 also ::1, but you can assign others too. Ethernet or WLAN have the IP addresses on the local network, i.e. 172.16.0.34 or whatever.
If you bind a socket for receiving data to a specific address you can only receive data sent to this specific IP address. For example, if you bind to 127.0.0.1 you will be able to receive data from your own system but not from some other system on the local network, because they cannot send data to your 127.0.0.1: for one any data to 127.0.0.1 will be sent to their own 127.0.0.1 and second your 127.0.0.1 is an address on your internal loopback interface which is not reachable from outside.
You can also bind a socket to a catch-all address like 0.0.0.0 (Ipv4) and :: (Ipv6). In this case it is not bound to a specific IP address but will be able to receive data send to any IP address of the machine.

Using socket in C how can I send message from IPv6 to IPv4?

I tried to convert the destination address to IPv6 format as ::ffff:IPv4. And use a socket of AF_INET6 type. It gives error: Network Unreachable. But using the same technique I am able to communicate from IPV4 to IPV6
Thanks for your help in advance.
IPv4 and IPv6 are separate protocols. They don't talk to each other.
On some operating systems you can use an IPv6 socket and accept incoming IPv4 connections on it. But that is just a software thing to make code development easier for server code. I have never seen that work for client code. You'll have to create the right socket type for that.
Usually you resolve a hostname using DNS, you'll get multiple answers (IPv4 and IPv6), you iterate over them creating the required socket type and try to connect. If it works you use that socket, if not you do the next iteration which creates a new socket etc.
If you code that is sensitive to delays you might want to implement the happy eyeballs algorithm.
On most systems, PF_INET6 sockets are able to communicate with IPv4 addresses by using addresses in the ::FFFF:0:0/96 range. However, this is only done at the level of the sockets library: the actual on-the-wire data are plain IPv4 packets (as though you had used an PF_INET socket), there is no protocol conversion in the network.
The error you receive indicates that you have no IPv4 route to the requested destination. This probably indicates that your host doesn't have an IPv4 default route. There is no solution to that — without IPv4 connectivity, there is nothing you can do to reach an IPv4 address.

Bypass default route for outgoing connections

I an writing a small application that needs to connect through one of multiple network interfaces on the machine. The interface is not the "default" one (the one with the default route). Is it possible to bind an outbound TCP socket directly to a specific interface?
Here is an example:
eth0: 192.168.1.10, gateway 192.168.1.1
eth1: 192.168.2.10, gateway 192.168.2.1
default gateway: 192.168.1.1
(both interfaces can reach the Internet through different external IPs)
Now, I want my application to use eth1 to connect to an external server, even if the system is configured to use eth0 for external traffic.
(The question is probably trivial, but I just wanted to know if it is possible at all before spending time on it)
Currently, I am using Python with Twisted, but if I have to use BSD sockets then so be it.
From: http://linux.about.com/od/commands/l/blcmdl7_socket.htm
SO_DONTROUTE - Don't send via a gateway, only send to directly connected hosts. The same effect can be achieved by setting the MSG_DONTROUTE flag on a socket send(2) operation. Expects an integer boolean flag.