How to bind a process to an IP address using ForceBindIP (on Windows)

Sometimes a peice of software does not provide a configuration option to specify the IP address to bind to on a multi-ip server (including GRE tunnels!). This is quite common in Windows software unfortunately. It is also not uncommon for UDP software to not respect source IPs and interfaces on Windows due to the network implementation (soft) under the hood.

It is possible to work around this issue on Windows without modifying the application or source (if available) by injecting a dll to override / detour the socket functions.

Steps

1. Get the shim (ForceBindIP)

The shim we are going to be using in this example was written by Richard Stanway. A copy of ForceBindIP can be obtained at his site

2. Using the shim

To use the compiled shim with your application or service it needs to be "preloaded" into the application. Richard has kindly provided an application for injecting the DLL into the target application. This is known as ForceBindIP or ForceBindIP64 for 64-bit applications.

To use this application simply run it with the first parameter being the IP address you wish to bind to and the second argument onwards being your application call. For an example of this in use see the Minecraft Bedrock on Windows Tutorial

NOTE: Visual C runtimes may be required. Please be sure to read the forcebindip download page for more information.

How this works

Warning: Technical Content ahead, feel free to skip

These days many systems are multi-homed in the sense that they have more than one IP address bound at the same time. These IP addresses could be additional IPs added to your server for additional HTTPS sites, services (where a specific port is required) or connected to different networks.

The kernel chooses an outgoing IP from the records matcing the destination from the routing table. Multiple routes are sorted based on the value of the metric:

Output of Route

It is possible to alter the metric and make the kernel router prefer the desired interface above others. However this will affect all applications and services on the server. This includes private services such as SSH, and makes it difficult to use the additional IP addresses on the server.

Applications / Services are able to choose to bind to a specific interface, and often provide the option via a configuration file to choose the network interface or IP address to bind to. Unfortunately not all applications and services provide this functionality, and hence it becomes necessary to add this functionality after the fact. Often this has to be done without knowledge of the underlying software's source code, either because it is closed source or where compilation is difficult.

To do this a DLL library is made to modify bind and connect to use a specific localaddress, regardless of the parameters given to them by the application or service. In doing such the application or service is hence bound to the localaddress for listening and connecting sockets. This is very similar to the LD_PRELOAD method used on Linux.