routing – C# HttpClient fails to connect when binding to non-default route interface, but curl works – Network Engineering Stack Exchange

I’m trying to send HTTP requests through specific network interfaces on my Raspberry Pi running .NET. I’ve written a C# program that creates an HttpClient bound to a specific interface. However, I’m encountering an issue where the client can only successfully connect through the interface that’s currently set as the default route, and will timeout otherwise.
Here’s a simplified version of my code:
public static HttpClient CreateBoundHttpClient(string interfaceName)
{
var @interface = NetworkInterface
.GetAllNetworkInterfaces()
.FirstOrDefault(i => i.Name == interfaceName);

if (@interface == null)
throw new ArgumentException($”Interface {interfaceName} not found.”);

var ipAddress = @interface
.GetIPProperties()
.UnicastAddresses
.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork)
?.Address;

if (ipAddress == null)
throw new InvalidOperationException($”No IPv4 address found for interface {interfaceName}.”);

var handler = new SocketsHttpHandler();

handler.ConnectCallback = async (context, cancellationToken) =>
{
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(ipAddress, 0));

try
{
await socket.ConnectAsync(context.DnsEndPoint, cancellationToken);
return new NetworkStream(socket, ownsSocket: true);
}
catch
{
socket.Dispose();
throw;
}
};

return new HttpClient(handler);
}

When I run my program, it attempts to make requests through both wlan0 and wlan1. Here are the results when wlan0 is the default route:
root@pi:~/Test $ ip route show default
default via 172.17.32.10 dev wlan0

root@pi:~/Test $ dotnet FreeWave.dll
wlan0 resp = OK
wlan1 = The request was canceled due to the configured HttpClient.Timeout of 10 seconds elapsing.

And when wlan1 is the default route:
root@pi:~/Test $ ip route show default
default via 172.17.32.10 dev wlan1

root@pi:~/Test $ dotnet FreeWave.dll
wlan0 = The request was canceled due to the configured HttpClient.Timeout of 10 seconds elapsing.
wlan1 resp = OK

Note that this does not seem to work either:
root@pi:~ $ ip route show default
default via 172.17.32.10 dev wlan0 proto dhcp src 172.17.34.168 metric 600
default via 172.17.32.10 dev wlan1 proto dhcp src 172.17.32.248 metric 601

Now, the interesting part is that curl works fine with both interfaces, regardless of which one is set as the default route:
curl –interface wlan0 https://api.ipify.org
curl –interface wlan1 https://api.ipify.org

Both of these curl commands succeed, even when the specified interface is not the default route.
I have attempted using a direct IP instead of a domain, thinking the issue could have been related to DNS resolution, but that did not seem to make a difference.
Note that this issue only seems to occur when both interfaces are connected to the same WiFi network.
My questions are:

Why does my C# code fail to connect through the non-default route interface, even though it successfully binds to it?
What might be causing this discrepancy between my C# code and curl?
How can I modify my code to achieve the same behavior as curl, allowing connections through any interface regardless of the default route?

Any insights or suggestions would be greatly appreciated!

Stay in the Loop

Get the daily email from CryptoNews that makes reading the news actually enjoyable. Join our mailing list to stay in the loop to stay informed, for free.

Latest stories

- Advertisement - spot_img

You might also like...