How to bind specific source IP address using Poco::Net::HTTPSClientSession - c++

I have a https client that can run on one of two redundant hosts. Would like the host that is the 'Active' client host to use a specific IP address as the source address so that traffic appears to be coming from one source. Low level OS network setup to allow this is all in place. Our https client is built using the Poco::Net::HTTPSClientSession class.
From reading about this situation binding the shared source IP address to the client socket is the standard solution. Attempted the following code:
// set the shared IP address and use 0 (represents wildcard) for port
Poco::Net::SocketAddress sa = Poco::Net::SocketAddress(ipAddress, 0);
// bind the shared IP address to the socket
Poco::Net::SecureStreamSocket sss;
sss.impl()->bind(sa);
Poco::Net::HTTPSClientSession session(sss);
Unfortunately, this doesn't work as the bind() is throwing Poco::InvalidAccessException and exception message is "Cannot bind() a SecureStreamSocketImpl". Looked at the Poco source and bind() is just throwing this exception. Seems to not be allowed.
How to make this work with Poco::Net::HTTPSClientSession class?
Is it even possible to make it work with this class?

Not currently possible - there is a pending issue for it. It will be done eventually but currently there's no timeframe.

Related

C++ / Qt: How can I detect when a hostname or IP address refers to the current system?

I'm writing a macOS C++ application using Qt that acts as both a UDP client and UDP server. The server functionality allows the user to configure which port the UDP packets will be received on, and the client functionality allows specifying both a target host and a port number. The host can be either a hostname or an IP address, including addresses or hostnames that resolve to a multicast or broadcast address.
In order to help prevent circularity, when the server functionality is enabled I need to be able to warn the user when the host and port they've entered for the client would send the packets directly to the app's server. Of course it's easy to check if the port numbers match, but this means I need to know whether the host they've entered refers to the current system.
Examples of hostnames or IP addresses that would typically be problematic:
127.0.0.1
localhost
192.168.1.255 (assuming the system is on a 192.168.1.0/24 subnet)
any of the IP addresses assigned to the current system's network interfaces
the system's local DNS name
any other loopback addresses that may be configured other than 127.0.0.1
How could I go about detecting this?
Since this app is being written using Qt, a solution that exclusively uses Qt's framework would be ideal. But if that's not possible (since Qt doesn't handle every possible use case) a macOS-specific solution will work too.
QNetworkInterface class should provide the most information you may need.
You can obtain a list of IP addresses using QNetworkInterface::allAddresses() static function.
You can also get a list of all interfaces using QNetworkInterface::allInterfaces().
Calling QNetworkInterface::addressEntries() for each QNetworkInterface returned by QNetworkInterface::allInterfaces() will give you more information about address entries for each interface.
auto ifs = QNetworkInterface::allInterfaces();
foreach (auto interface , ifs){
auto addresses = interface.addressEntries();
foreach ( auto addy , addresses){
///play with the addy here.
}
}
You can also test hostnames against those ip addresses which you are going to ban, using QDnsLookup class.

Can I call bind() and then connect() on same socket descriptor?

Just a curious question about networking socket programming in a Windows Application with C/C++:
How can I tell the connect() function to use a particular source IP and source port values?
After a socket is created, application calls connect() to remote IP and port by using the sockaddr structure.
the connect() function internally selects the source IP and port for the connection.
Rather than the system deciding the source IP and/or port for the connect(), let that be the application's responsibility to decide which source IP and/or port to bind to.
bind() requests port that is not in use so it can claim it and become a server, while connect() wants a port that is already in use, so it can connect to it and talk to the server.
As user stark said, you need to call bind if you want to specify which interface/port combination to use, although if you want next call to bind it to a random available port number, you can opt out from bind() call because client doesn't necessarily has to have a fixed port number.
It is possible to ask the kernel to select a specific port before calling connect(), but if I may ask - why you wouldn't want to kernel to allocate source ports, as far as I know it's not best practice.
How can I tell the connect() function to use a particular source IP and source port values?
Use the socket library's bind() function for that. Yes, you can call bind() before connect() for an outgoing socket. That is a perfectly legitimate operation for both UDP and TCP sockets.
Yes, you can. Indeed there's a reason to do that: In case your routing policy makes your connection to be established from an IP address which is not the one you want to use, you can force in a multihomed/routing host a specific IP address as source by means of bind(2) system call. Another use is to specify a fixed source port for the connection, but this is not as usual as the previous case.
But beware: you can select only one of the already configured IP addresses you have, not any address you can imagine.

How to make a .cpp file to act as an accessible server

I have written a simple program with Linux (Cent OS 7.0) and C++. It is a very small server which sends back a string of characters to the client. But my problem is that I don't know how should I access that server using an IP address?
I have used Linux Socket Interface (Berkeley), and in the section which defines the address, my code does the following:
serverObject.
sin_family = AF_INET;
serverObject.sin_addr.
s_addr = htonl(INADDR_ANY);
serverObject.
sin_port = htonl(portNumber);
I use INADDR_ANY as my server's address which is defined in its definition as:
/* Address to accept any incoming messages. */
Now, how should I run the server, and then use my simple client program to send request to it. My simple client program accepts an IP address as it's destination address, this address should be the one destined toward to the server. How should I relate it then?
INADDR_ANY goes to specify that all active network interfaces in the system should be bound to. So if you're connected to more than one network, you'll be able to communicate with connections coming in from all of them. Most systems will usually have just one, though, and this still goes to say that if the IP bound to that interface happens to change, you'll still bind to that interface.
So, once you specify INADDR_ANY, you need to initiate connections according to the following rules:
If you're connecting from the same physical machine, the easiest thing would be to use the loopback interface (127.0.0.1). However, you can still do (2).
If you're connecting from another machine, you need to pick the accessible IP address of your server from that machine. As said above, if your server is only connected to one network, this will simply be the IP address of the server. Within an internal network this will often be something like 192.168.x.y, or 10.0.x.y—but it doesn't have to.
If you're connecting from a different network which uses a gateway to access your server, then you will need to set up port forwarding in the relevant routers so that when they receive connection to port X, they will know to internally transfer it to your server.
As a server programmer, you decide the port on which to listen, but not the address.
The internet address is provided by your internet provider, or 127.0.0.1 to test on your own machine.
There are plenty of web pages on internet that provide tools to tell you your current public address (search for What is my Ip).
Most of the "home" internet routers implement NAT: they have a single internet address and map them to many device, that carry the Port number to be changed (your port 80 become port (e.g.) 2345 for outside). To allows a client from outside your home to access your server, you are required to configure your router to map the server port, so for example your public port 80 map to your server port 80.
With that said, you should be able to connect your client to your server through an address and port.
If then you want to use a name (example.org) instead of an IP (93.184.216.34), a Domain Name Server is used. But that is another topic.

Any ip and local ip binding?

I'm working on a network platform that creates a basic I/O interface for make something fast/easy. I need to understand this, what is the main differences between binding any ip or local ip to socket? Why I need to bind local ip, why I need to bind any ip? Simple but important question :)
Binding a server socket to a local ip instead of to 0.0.0.0 can act like a poor man's firewall if you want to have a server that is not open to the entire world, but only to a specific group.
For example:
- You can bind a socket to the local ip if you want it to be used a way for different processes in the same machine to communicate.
- You can bind a socket to an ip if you want all access to it to occur through some external load balancer.
Remember that a TCP connection is made up of four things: Source address, source port number, destination address and destination port number.
When e.g. a server program binds a socket to a local address, two of those things are provided, and allows clients to connect to a well know destination.
When you bind to any address, it doesn't actually bind to any address, it just creates the binding for all local addresses. (For hosts that have multiple interfaces, which all hosts have.)

Accepting Sockets Only From Specific IPs

My game server is now accepting sockets from every one. But how can I block specific IPs from attack? You know, if they would like to crash my server or something. I'm using SFML library, C++.
With TCP, when your program (or the library you are using) calls accept(2), the second argument is an output which tells you the client's address.
With UDP there are no connections, but there is recvfrom(2), which just like accept(2), gives you the peer's address. So you can ignore the peers you don't like.
Or you can run your server behind some sort of firewall appliance and add rules there, or use iptables or similar as a software firewall on the host machine.
In SFML you have SocketTCP::Accept and SocketUDP::Receive, both of which will give you the peer's address if you pass an empty address as an argument.
I don't know of any specific method for blocking some ips, but you can surely reject the request (probably connection request in your case) after determining the originating ip. Maintain a list of blocked ip (or BlackListed ip) (make it configurable as well for easier additions/deletions) and reject the request if it is coming from one of the Black Listed ips.
Under Windows, WinSock 2.x has an optional callback parameter for WSAAccept() that can be used to conditionally accept/reject connection requests. Client IP/Port is one of the available parameters.