Qt5 Bind TCP Socket on Multihomed Network - c++

I am having troubling using the new bind feature of the QTcpSocket class in Qt5. Any help figuring this out would be appreciated.
I have a multihomed server that contains two NICs each with a separate IP address. I have setup routing on the servers so that sending from the source address is sent out of the appropriate NIC regardless of the target remote address. That is, sending from x.x.x.0 goes out over eth0 and x.x.x.1 goes out over eth1 regardless of who the data is being sent to. These NICs are connected via ethernet to long range Wifi links that are then connected to a switch. These wifi links act as a transparent bridge and can rather be seen as two ethernet cables (but they are limited in bandwidth). The switch is then connected to a computer. The goal is to transfer data between the server and the computer, and to use the two wifi links in parallel to increase bandwidth. Although the server is physically a server, the software has the computer running as the software server (as others connect to it). That is, the physical server (software client) opens TCP sockets and attempts to connect to the listening computer (software server).
I use the bind feature of Qt5 to bind one TCP socket to the eth0 IP address and bind another TCP socket to the eth1 IP address. I have verified this works with other programs like PING or file transfer via SCP. See http://qt-project.org/doc/qt-5.0/qtnetwork/qabstractsocket.html#bind
When I call bind the call succeeds and subsequent requests for the local IP address returns the correct value. E.g. socket->bind(ip) returns true and then socket->localAddress() equals ip. However, when I call connectToHost the localAddress is lost when it starts the connection attempt and after connecting it has a different localAddress that is not the one I wanted it to have.
Can anyone shed light into what is going on? I am trying to avoid rewriting the software to reverse the roles of software client / server as these programs are quite big. Thanks for the help.

There is an open bug on this in the Qt project bug tracker.

Related

iOS NAT64 IPv6 environment issue

Now that apple has changed their review environment to an IPv6 only network ive been running into troubles with my application while testing.
The application requires the user to input their server/systems IP address, port (4401) and credentials to gain access to the application. Following the guidelines provided by apple i set up a NAT64 environment to test my application's compatibility. Running iOS 9.3.2 on an iphone 5s.
My work environment has several internal networks. I connected my iMac to the internal server (10.10.50.XX) via Ethernet which also has an external IP which is what i provide to apple. The 50 network does not run behind a proxy, but there are some sites which get filtered, but can access by confirming. I then shared my Ethernet connection through WiFI.
I connected the device and had internet access with the same pages being filtered. The device gets assigned a local-link address of 169.254.XX.XX. From what ive read my device is connecting to the ipv6 only network correctly, as the iphone does not show the ipv6 address only local link.
If I am correctly connected to the shared IPv6 network, the problem I am having is connecting to my server on the 50 network from my application. The application fails when ever i try to connected to the 10.10.50.XX network or the external(understandable because my imac is on the 50 internal network) .
Testing the application using IPv4 with a wireless router that is connected to the 50 network runs perfectly.I think it is an issue with the local link address not being able to see the 50 network or something.
Heres some brief background info on how i connect to the server. The user inputs all the credentials and the IP address and port of the server they want to connect to. The application saves this as a text (utf-8) and uses boost shared_ptr to send it to the cpp connection class which validates the credentials and provides access to the user. This cpp connection class handles the connection, synchronization, logging, requests and response from the server.
Is it possible to somehow get access to the 50 network, using the NAT64 internet sharing option?
If you're passing an IP address straight down to your network lib, then no. When your device is on the IPv6-only side of the NAT64, the server's IPv4 address is useless.
You almost certainly need a DNS name for the server you're trying to reach. The NAT64 relies first on DNS64 to create IPv6 addresses for your application when the server is IPv4-only. These synthesised addresses contain the IPv4 address(es) for the server, giving the NAT64 the information it needs to translate from IPv6 to IPv4.
Updating this to add: as suggested by user102008 in the comment thread attached to this answer, you may also be able to pass the IPv4 string literal though getaddrinfo() (see code listing 10-1 on this page). When you're behind a NAT64, a synthesised IPv6 address should be among the results returned by that call. The NAT64 will translate from this address back to IPv4 to reach the host you specified. In this case, if the system knows the correct prefix to use for the NAT64, a hostname is not necessary.

Uniquely Identify UDP Connection - Multiple Connections from same IP

I'll start by saying that currently my server identifies based on sender IP, that is the IP of the client.
Now I am programming a game server (just for practice) and this got me thinking how do I uniquely identify a client if they are on the same IP. (Two players open a connection on the same machine / same network so the outward IP is the same).
I've searched for an answer both on google and here and gamedev.net but am unable to find what I am looking for, likely because I do not know the correct terms to query for.
Any guidance on this would be appreciated, especially in regards to efficiency and best practice.
Thanks.
There is no "connection" term in all stuff related to UDP, but it is common that an application that initiates a UDP socket maintains the same source port over the time, so you could identify it by source IP-port.
There is some stuff related to maintain communication between a client inside a NAT router (in NAT-UDP the client is the first host that send a UDP datagram to another host and trigger a new connection tracking entry) and a server.
This "connection tracking" is only for allow traffic from outside to inside, making a "temporal" relationship (with a timeout), that probably will not be used anymore (only once) sometimes.
If the server doesn't use the same destination port in outcoming datagram as source port in incoming one, the router won't send the datagram to the host inside NAT.
Best regards.

C++ sockets: communication between PCs over internet

I'm writing a program on Windows using winsocks that can send messages to another computer. The client connects with the server in the other computer and begin exchanging data.
It works fine on my local network using local addresses(192.168.1.*), but I can't communicate with public addresses (216.185.45.129); not even my own. I can successfully connect to a website on port 80, but not to my laptop at home using its public IP address, regardless of what ports I use (unreserved ports).
So I did research online and the only solution that seems to work is port forwarding.
-But is there absolutely no other way to achieve this?
-How do other programs like Teamviewer connect to other computers on the network then?
-Is there an already open but typically unused port that I can use?
-At the very least, can I forward the ports on my router but not have the client do anything? Or maybe have my program forward the ports automatically.
The main problem is, that every router is using NAT to distinguish different computer in your lokal network against the WAN. He need to do this, because you got only one IP in the internet, but several devices in your home. To archive this, he uses groups of ports. That means, if you use to send maybe from port 2048 to a webserver in internet with two devices, the router gives one device another port (like 2049). The response has the Port of the requester, so the router can map it back. Unfortunately most router always map ports so you never now which port you have from the internet side.
There are two common ways to work around and archive your goal.
Port Fowarding
You can force most router not to map special ports but bind them to unique MAC addresses. You can use UPNP to config most router to do that, but I do not recommend that for security reasons and also it does not work in many enviroments where Router do not allow UPNP manipulation.
Most router have port forwarding abilities for gaming reasons (mostly it is used in P2P networks)
It works with TCP and UDP.
NAT Traversal
The common way is NAT traversal, also known as NAT hole punching. I will describe it in short for UDP. You can find a wiki explanation here for TCP and for UDP here. Unfortunately you need a server in the internet both clients can reach. Here the steps:
Both clients contact the server. The server now know IP and PORT of both clients.
Server send back the information to the clients.
Both(!) clients send now packages to each other on the known address.
It is necessary that both client send a UDP package and have to accept that the first package get lost. The reason is the router. Most router only accept packages from a source on a mapped PORT if a client has send a package to that source before.
UPDATE
Regarding to a comment of Remy Lebau I changed the Firewall piercing part to NAT Traversal as it was partly wrong.

how to get IP address of a computers that is directly connected to my PC

I'm trying to write a function that can get me the IP adress (and the name of the device as bonus) of devices that are in my network, the network is gonna be a direct connection between two computers using Ethernet cable or creating an access point (using wi-fi)
I tried to search about how to do it but it seems like I need to listen to the network or something which seems to be difficult.
hope you can guide me to what I should do or read to get started.
Note: I'm using Windows on both computers.
Edited:
P.S: I need the IP Address so I can send a message to the other computer using winsock in a Client/Server program I wrote.
can't I make the server send its IP to the client or the opposite ?
If your software is running on both machines, you can have one (or both) machines send out a particular broadcast (or, if you prefer, multicast) UDP packet on a specific port. Your program should also be listening on that same port. When it receives that packet (using recvfrom()), recvfrom()'s fifth argument will contain the IP address of the machine that sent the packet, i.e. the IP address you want.
(If OTOH your software is not running on the remote machine, you'll need to use some more general-purpose discovery mechanism such as mDNS or LLDP -- hopefully you won't have to do that, though, as it's a good deal more complicated)

TCP simultaneous open and self connect prevention

TCP standard has "simultaneous open" feature.
The implication of the feature, client trying to connect to local port, when the port is from ephemeral range, can occasionally connect to itself (see here).
So client think it's connected to server, while it actually connected to itself. From other side, server can not open its server port, since it's occupied/stolen by client.
I'm using RHEL 5.3 and my clients constantly tries to connect to local server.
Eventually client connects to itself.
I want to prevent the situation. I see two possible solutions to the problem:
Don't use ephemeral ports for server ports.
Agree ephemeral port range and configure it on your machines (see ephemeral range)
Check connect() as somebody propose here.
What do you thinks?
How do you handle the issue?
P.S. 1
Except of the solution, which I obviously looking for,
I'd like you to share your real life experience with the problem.
When I found the cause of the problem, I was "astonished" on my work place people are not familiar with it. Polling server by connecting it periodically is IMHO common practice,
so how it's that the problem is not commonly known.
When I stumbled into this I was flabbergasted. I could figure out that the outgoing
port number accidentally matches the incoming port number, but not why the TCP
handshake (SYN SYN-ACK ACK) would succeed (ask yourself: who is sending the ACK if
there is nobody doing a listen() and accept()???)
Both Linux and FreeBSD show this behavior.
Anyway, one solution is to stay out of the high range of port numbers for servers.
I noticed that Darwin side-steps this issue by not allowing the outgoing port
to be the same as the destination port. They must have been bitten by this as well...
An easy way to show this effect is as follows:
while true
do
telnet 127.0.0.1 50000
done
And wait for a minute or so and you will be chatting with yourself...
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
hello?
hello?
Anyway, it makes good job interview material.
Bind the client socket to port 0 (system assigns), check the system assigned port, if it matches the local server port you already know the server is down and and can skip connect().
For server you need to bind() socket to port. Once addr:port pair had socket bound, it will no longer be used for implicit binding in connect().
No problem, no trouble.
Note that this solution is theoretical and I have not tested it on my own. I've not experienced it before (or did not realize) and hopefully I won't experience it anymore.
I'm assuming that you cannot edit neither the client source code nor the server source. Additionally I'm assuming the real problem is the server which cannot start.
Launch the server with a starter application. If the target port that the server will bind is being used by any process, create an RST (reset packet) by using raw sockets.
The post below briefly describes what an RST packet is (taken from http://forum.soft32.com/linux/killing-socket-connection-cmdline-ftopict473059.html)
You have to look at a "raw socket" packet generator.
And you have to be superuser.
You probably need a network sniffer as well.
http://en.wikipedia.org/wiki/Raw_socket
http://kerneltrap.org/node/3072 - TCP RST attacks
http://search.cpan.org/dist/Net-RawIP/lib/Net/RawIP.pm - a Perl module
http://mixter.void.ru/rawip.html - raw IP in C
In the C version, you want a TH_RST packet.
RST is designed to handle the following case.
A and B establish a connection.
B reboots, and forgets about this.
A sends a packet to B to port X from port Y.
B sends a RST packet back, saying "what are you talking about? I don't
have a connection with you. Please close this connection down."
So you have to know/fake the IP address of B, and know both ports X
and Y. One of the ports will be the well known port number. The other
you have to find out. I thnk you also need to know the sequence
number.
Typically people do this with a sniffer. You could use a switch with a
packet mirroring function, or run a sniffer on either host A or B.
As a note, Comcast did this to disable P2P traffic.
http://www.eff.org/wp/packet-forgery-isps-report-comcast-affair
In our case we don't need to use a sniffer since we know the information below:
So you have to know/fake the IP address of B, and know both ports X
and Y
X = Y and B's IP address is localhost
Tutorial on http://mixter.void.ru/rawip.html describes how to use Raw Sockets.
NOTE that any other process on the system might also steal our target port from ephemeral pool. (e.g. Mozilla Firefox) This solution will not work on this type of connections since X != Y B's IP address is not localhost but something like 192.168.1.43 on eth0. In this case you might use netstat to retrieve X, Y and B's IP address and then create a RST packet accordingly.
Hmm, that is an odd problem. If you have a client / server on the same machine and it will always be on the same machine perhaps shared memory or a Unix domain socket or some other form of IPC is a better choice.
Other options would be to run the server on a fixed port and the client on a fixed source port. Say, the server runs on 5000 and the client runs on 5001. You do have the issue of binding to either of these if something else is bound to them.
You could run the server on an even port number and force the client to an odd port number. Pick a random number in the ephemeral range, OR it with 1, and then call bind() with that. If bind() fails with EADDRINUSE then pick a different odd port number and try again.
This option isn't actually implemented in most TCPs. Do you have an actual problem?
That's an interesting issue! If you're mostly concerned that your server is running, you could always implement a heartbeat mechanism in the server itself to report status to another process. Or you could write a script to check and see if your server process is running.
If you're concerned more about the actual connection to the server being available, I'd suggest moving your client to a different machine. This way you can verify that your server at least has some network connectivity.
In my opinion, this is a bug in the TCP spec; listening sockets shouldn't be able to send unsolicited SYNs, and receiving a SYN (rather than a SYN+ACK) after you've sent one should be illegal and result in a reset, which would quickly let the client close the unluckily-chosen local port. But nobody asked for my opinion ;)
As you say, the obvious answer is not to listen in the ephemeral port range. Another solution, if you know you'll be connecting to a local machine, is to design your protocol so that the server sends the first message, and have a short timeout on the client side for receiving that message.
The actual problem you are having seems to be that while the server is down, something else can use the ephemeral port you expect for your server as the source port for an outgoing connection. The detail of how that happens is separate to the actual problem, and it can happen in ways other than the way you describe.
The solution to that problem is to set SO_REUSEADDR on the socket. That will let you create a server on a port that has a current outgoing connection.
If you really care about that port number, you can use operating specific methods to stop it being allocated as an ephemeral port.