You can use Linux network namespaces to create a namespace for each interface, then use "ip netns exec <command_and_args>" to run your Selenium processes with whatever namespace (interface) you desire.
Below is from a real working example with two interfaces...
eth0: 172.20.0.0/16
eth1: 172.21.0.0/16
To validate the test, I had two Apache httpd servers, one on each network...
eth0 httpd: 172.20.0.3
eth1 httpd: 172.21.0.3
This was on Alpine Linux... so I installed iproute2 to get ip netns
...
/ # apk update
/ # apk add iproute2
The two namespaces I created were...
eth0 namespace: eth0ns # The 172.20.0.0/16 network.
eth1 namespace: eth1ns # The 172.21.0.0/16 network.
Remaining setup (adding namespaces, route in each namespace, see phantomjs tests further below)...
/ # ip netns add eth0ns
/ # ip netns add eth1ns
/ # ip link add link eth0 eth0ns netns eth0ns type ipvlan mode l2
/ # ip link add link eth1 eth1ns netns eth1ns type ipvlan mode l2
/ # ip -n eth0ns link set lo up
/ # ip -n eth0ns link set eth0ns up
/ # ip -n eth1ns link set lo up
/ # ip -n eth1ns link set eth1ns up
/ # ip addr
...
126: eth0@if127: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
...
inet 172.20.0.2/16 brd 172.20.255.255 scope global eth0
valid_lft forever preferred_lft forever
128: eth1@if129: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
...
inet 172.21.0.2/16 brd 172.21.255.255 scope global eth1
valid_lft forever preferred_lft forever
Add routes...
/ # ip -n eth0ns addr add 172.20.0.2/16 dev eth0ns
/ # ip -n eth0ns route add default via 172.20.0.1 dev eth0ns
/ # ip -n eth1ns addr add 172.21.0.2/16 dev eth1ns
/ # ip -n eth1ns route add default via 172.21.0.1 dev eth1ns
If you have issues adding routes, you can delete any existing ones first... for example...
/ # ip netns exec eth1ns route del default
/ # ip netns exec eth1ns route add default gw 172.21.0.1 eth1ns
/ # ip netns exec eth1ns route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.21.0.1 0.0.0.0 UG 0 0 0 eth1ns
172.21.0.0 * 255.255.0.0 U 0 0 0 eth1ns
/ #
Add DNS for each namespace. Note, 10.5.20.5 was my test DNS, and both networks were connected to outside world as well (see ping test below)...
/ # cat /etc/resolv.conf
# my dns
nameserver 10.5.20.5
#nameserver 127.0.0.11
options ndots:0
/ # cat /etc/netns/eth0ns/resolv.conf
# my dns
nameserver 10.5.20.5
#nameserver 127.0.0.11
options ndots:0
/ # cat /etc/netns/eth1ns/resolv.conf
# my dns
nameserver 10.5.20.5
#nameserver 127.0.0.11
options ndots:0
Traceroute test to show two different interfaces being used depending on namespace used with ip netns exec
...
ip netns exec eth0ns <cmd>
will cause cmd to use eth0.
ip netns exec eth1ns <cmd>
will cause cmd to use eth1.
/ # ip netns exec eth0ns traceroute -m 1 google.com
traceroute to google.com (142.251.33.110), 1 hops max, 46 byte packets
1 172.20.0.1 (172.20.0.1) 0.002 ms 0.002 ms 0.001 ms
/ # ip netns exec eth1ns traceroute -m 1 google.com
traceroute to google.com (142.251.33.110), 1 hops max, 46 byte packets
1 172.21.0.1 (172.21.0.1) 0.003 ms 0.001 ms 0.002 ms
Ping tests:
Without any namespace, neither httpd server can be accessed...
/ # ping -w 2 172.20.0.3
PING 172.20.0.3 (172.20.0.3): 56 data bytes
--- 172.20.0.3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
/ # ping -w 2 172.21.0.3
PING 172.21.0.3 (172.21.0.3): 56 data bytes
--- 172.21.0.3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
172.20.0.0/16 network namespace, only its httpd server can be accessed...
/ # ip netns exec eth0ns ping -w 2 172.20.0.3
PING 172.20.0.3 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.075 ms
64 bytes from 172.20.0.3: seq=1 ttl=64 time=0.070 ms
--- 172.20.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.072/0.075 ms
/ # ip netns exec eth0ns ping -w 2 172.21.0.3
PING 172.21.0.3 (172.21.0.3): 56 data bytes
--- 172.21.0.3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
172.21.0.0/16 network namespace, only its httpd server can be accessed...
/ # ip netns exec eth1ns ping -w 2 172.21.0.3
PING 172.21.0.3 (172.21.0.3): 56 data bytes
64 bytes from 172.21.0.3: seq=0 ttl=64 time=0.067 ms
64 bytes from 172.21.0.3: seq=1 ttl=64 time=0.068 ms
--- 172.21.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.067/0.067/0.068 ms
/ # ip netns exec eth1ns ping -w 2 172.20.0.3
PING 172.20.0.3 (172.20.0.3): 56 data bytes
--- 172.20.0.3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
/ #
Curl test, remember that 172.20.0.3 is on one network and 172.21.0.3 on the other, so below you see 4 tests, pass/fail to show each process can only access its respective network's httpd server...
/ # ip netns exec eth0ns curl -m 3 http://172.20.0.3
<html><body><h1>It works!</h1></body></html>
/ # ip netns exec eth0ns curl -m 3 http://172.21.0.3
curl: (28) Connection timed out after 3001 milliseconds // expected, different network.
/ # ip netns exec eth1ns curl -m 3 http://172.21.0.3
<html><body><h1>It works!</h1></body></html>
/ # ip netns exec eth1ns curl -m 3 http://172.20.0.3
curl: (28) Connection timed out after 3002 milliseconds // expected, different network.
/ #
Install phantomjs and perform a similar tests.
/ # #Install phantomjs
/ # cat show_content.js
var webPage = require('webpage');
var system = require('system');
var page = webPage.create();
page.settings.resourceTimeout = 5000
page.onResourceTimeout = function(e) {
console.log(e.errorCode);
console.log(e.errorString);
console.log(e.url);
phantom.exit(1);
};
page.open(system.args[1], function (status) {
var content = page.content;
console.log('Content: ' + content);
phantom.exit();
});
/ # ip netns exec eth0ns phantomjs show_content.js http://172.20.0.3
...
Content: <html><head></head><body><h1>It works!</h1>
</body></html>
/ # ip netns exec eth0ns phantomjs show_content.js http://172.21.0.3
...
408
Network timeout on resource.
http://172.21.0.3/
/ # ip netns exec eth1ns phantomjs show_content.js http://172.21.0.3
...
Content: <html><head></head><body><h1>It works!</h1>
</body></html>
/ # ip netns exec eth1ns phantomjs show_content.js http://172.20.0.3
...
408
Network timeout on resource.
http://172.20.0.3/
/ #
If not obvious, after getting your network namespaces setup, you use the ip netns exec <ns> <cmd>
command to run a process having access only to that namespace's interface...
ip netns exec eth0ns <cmd>
to run a process using eth0 172.20.0.0/16
ip netns exec eth1ns <cmd>
to run a process using eth1 172.21.0.0/16