Как выйти в интернет по определенному интернет-соединению, если имеется несколько интернет-соединений?

Имеется: комп (windows/linux на выбор) с несколькими usb входами, в каждом по usb/sim модему. Соответственно, единовременно на компе имеется несколько интернет-соединений.

Вопрос: как выйти в интернет программе на C# по определенному интернет-соединению. При этом, другие программы, которые используют другие интернет-соединения не должны лишиться доступа к интернету.

Несколько виртуалок: создать несколько виртуалок, в каждую завести по 1 интернет-соединению, и в каждой запускать необходимый софт - не подходит. Ибо периодически, необходимо выйти в интернет с другого интернет-соединения...

В какую сторону копать, что почитать?


Ответы (3 шт):

Автор решения: eri

Для начала каджому модему надо задать свой адрес, для примера 192.168.4.1.

Потом добавим маршрутизацию по метке - метка 4 отправляется в таблицу 4:

ip route add table 4 default via 192.168.4.1
ip rule add fwmark 4 table 4

Теперь поставим метку программе по группе процессов (Главная + подпроцессы). Группу процессов можно найти например так:

SID=`ps -eo sid,args |grep имяпрограммы |head -n 1 |cut -b 1-5`

И установка метки:

iptables -t mangle -A OUTPUT -p TCP -m owner --sid-owner $SID -j MARK --set-mark 4

Теперь всё что вышло из этой программы уйдет в 192.168.4.1.

И пара правил чтоб пофиксить ресолвер:

ip rule add to 192.168.0.0/16 table main
→ Ссылка
Автор решения: eri

Для примера интерфейс модема eth1. Создаем неймспейс TESTA, переносим туда модем, поднимаем сеть:

# ip netns add TESTA
# ip link set dev eth1 netns TESTA
# ip netns exec TESTA ip link set dev eth1 up
# ip netns exec TESTA dhcpcd eth1

Из основной системы интерфейс пропадет. Также подпортится resolv.conf, исправим на внешний:

# echo nameserver 8.8.8.8 > /etc/resolv.conf

И можно запускать программу в собственной сети:

$ xhost +
$ sudo ip netns exec TESTA su eri -c "DISPLAY=$(DISPLAY) opera --user-data-dir=/home/eri/.opera_TESTA/"
→ Ссылка
Автор решения: PashaPash

В C# (и не только в C#) можно явно указать локальный ip/интерфейс, с которого будут открываться соедниения, и тем самым, выбрать конкретное подключение.

Способ указания зависит от используемого варианта работы с сетью.

При работе через TCPClient можно явно передать local endpoint в констуктор:

//Creates a TCPClient using a local end point.
IPAddress ipAddress = Dns.GetHostEntry (Dns.GetHostName ()).AddressList[0];
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 0);
TcpClient tcpClientA = new TcpClient (ipLocalEndPoint);

При работе через HttpWebRequest [можно выбрать исходящий адрес в коллбеэке SericePoint.BindIPEndPointDelegate]:

var req = WebRequest.CreateHttp("https://ru.stackoverflow.com/");

req.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
    new IPEndPoint(IPAddress.Parse(localIP), 0);

При работе через WebClient можно переопределить GetWebRequest, сведя выбор к решению для WebRequest:

class CustomWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        var req = (HttpWebRequest)base.GetWebRequest(address);

        req.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
            new IPEndPoint(IPAddress.Parse(localIP), 0);

        return req;
    }
}
→ Ссылка