Score:1

Connecting to Multiple cameras which each acts as a WiFi Access Point

id flag

I have 7 cameras each acting as a WiFi Access Points and I can not change their configurations.

Camera1 SSID: camera1, pass: 1234, it has static IP: 192.168.42.1 and built-in DHCP server
Camera2 SSID: camera2, pass: 1234, it has static IP: 192.168.42.1 and built-in DHCP server
..
Camera7 SSID: camera7, pass: 1234, it has static IP: 192.168.42.1 and built-in DHCP server

From my windows notebook, by using internal WiFi adaptor, I can connect to camera1's ssid and get videos. Then I need to disconnect from it, connect to camera2's ssid to get video from camera2, and similar to 3,4..7.

What I want is to get simultaneous videos from all of them.

What I tried: I tried to plug 7 USB WiFi adaptors to my notebook. And each adaptors configured to connect different cameras. In this case, windows shows 7 different ethernet interfaces and each gets their IP from corresponding camera's dhcp server. But all cameras use same IP which is 192.168.42.1. Also as I learnt multiple USB WiFi adaptors are supported by Windows but not by MACOS.

I need a kind of universal solution to this problem, so far I couldn't figure it out how. Your helps and suggestions are highly appreciated.

Thanks.

Further tests: I believe that I'm close to a solution. But still need help. I took a Raspberry Pi 4 which runs Ubuntu on it. I'm intended to use it as a router. By Default PI hardware comes with 2 ethernet interfaces;

  1. eth0 -> 1Gbit cable connection
  2. wlan0 -> Embedded WiFi interface

I plugged two extra USB WiFi dongles and now it has two more ethernet interfaces named wlxb8b7f16a0602 and wlxb8b7f16a04cd. Each USB WiFi dongle connected to a different camera. Here is the ifconfig output:

pi@pi:~$ ifconfig -a
eth0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether dc:a6:32:48:55:70  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.205  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::2c43:aa7a:a4c8:47eb  prefixlen 64  scopeid 0x20<link>
        inet6 2a02:aa14:c480:6c80:9deb:968e:785d:159c  prefixlen 64  scopeid 0x0<global>
        inet6 2a02:aa14:c480:6c80:10b7:8a65:dce6:1f5c  prefixlen 64  scopeid 0x0<global>
        ether dc:a6:32:48:55:71  txqueuelen 1000  (Ethernet)
        RX packets 10535  bytes 2218695 (2.2 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 44536  bytes 63167704 (63.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlxb8b7f16a0602: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.42.24  netmask 255.255.255.0  broadcast 192.168.42.255
        inet6 fe80::6523:f6cd:520b:ee0  prefixlen 64  scopeid 0x20<link>
        ether b8:b7:f1:6a:06:02  txqueuelen 1000  (Ethernet)
        RX packets 9  bytes 1495 (1.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 47  bytes 9334 (9.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlxb8b7f16a04cd: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.42.170  netmask 255.255.255.0  broadcast 192.168.42.255
        inet6 fe80::ad02:2e2e:cc11:c309  prefixlen 64  scopeid 0x20<link>
        ether b8:b7:f1:6a:04:cd  txqueuelen 1000  (Ethernet)
        RX packets 60  bytes 6531 (6.5 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 130  bytes 19353 (19.3 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

In this configuration;

  • eth0 -> not connected
  • wlan0 -> connected to my internet modem (used only for ssh to pi)
  • wlxb8b7f16a0602 -> connected to Camera1
  • wlxb8b7f16a04cd -> connected to Camera2

Even though each camera has same IP which is 192.168.42.1, since they are connected to different interfaces, I could ping them successfully by using -I parameter like below:

For Camera1:

pi@pi:~$ ping -I wlxb8b7f16a0602 192.168.42.1
PING 192.168.42.1 (192.168.42.1) from 192.168.42.24 wlxb8b7f16a0602: 56(84) bytes of data.
64 bytes from 192.168.42.1: icmp_seq=2 ttl=64 time=3.77 ms

For Camera2:

pi@pi:~$ ping -I wlxb8b7f16a04cd 192.168.42.1
PING 192.168.42.1 (192.168.42.1) from 192.168.42.170 wlxb8b7f16a04cd: 56(84) bytes of data.
64 bytes from 192.168.42.1: icmp_seq=2 ttl=64 time=2.03 ms

From here, let's say I assign a static IP to my eth0 interface which is 192.168.42.250

I want to forward requests come from

  • 192.168.42.250:443 at eth0 to 192.168.42.1:443 at wlxb8b7f16a0602
  • 192.168.42.250:444 at eth0 to 192.168.42.1:443 at wlxb8b7f16a04cd

If you help me for this remaining point, I accept your answer.

To @A.B:

pi@pi:~$ iw phy phy0 |grep netns
        phy <phyname> set netns { <pid> | name <nsname> }
                    <nsname> - change network namespace by name from /run/netns
                               or by absolute path (man ip-netns)


pi@pi:~$ ll /sys/class/ieee80211
total 0
drwxr-xr-x  2 root root 0 Mai 27 17:13 ./
drwxr-xr-x 78 root root 0 Jan  1  1970 ../
lrwxrwxrwx  1 root root 0 Jun 27 20:18 phy0 -> ../../devices/platform/soc/fe300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1/ieee80211/phy0/
lrwxrwxrwx  1 root root 0 Mai 27 17:13 phy1 -> ../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.2/1-1.2:1.0/ieee80211/phy1/
lrwxrwxrwx  1 root root 0 Mai 27 17:13 phy2 -> ../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/ieee80211/phy2/
Michael Hampton avatar
cz flag
Have you considered returning this garbage and buying a more reasonable camera solution?
Mehmet Fide avatar
id flag
@MichaelHampton Unfortunately this is not possible. Isn't there a kind of router which can connect to different wifi access points at the same time and combine them under one network? Theoretically It should be possible.
Ron Trunk avatar
in flag
@MehmetFide It's not possible if all your devices have the same address. Imagine if all your friends/family had the same telephone number.
A.B avatar
cl flag
A.B
@RonTrunk I'd say it's possible (probably not on Windows) with policy routing (with the interface as selector rather than the IP address), then as an example on Linux with conntrack zones to separate the identical looking flows in the subsequent NAT, or with network namespaces + NAT. But that would be very awkward to implement
Ron Trunk avatar
in flag
@A.B I suppose one could come up with some custom hardware/software do do whatever you want, but that's not practical. I imagine that if Mehmet had that kind of capability, he wouldn't have asked the question.
Mehmet Fide avatar
id flag
For example, any solution with a raspberry 4 as a router which works on Linux and attached 7 USB WiFi dongle on it would be appreciated. It would definitely be accepted by me. With the configuration, I would have one 1Gbit Ethernet port with a cable (that can go to windows or macos) and 7 WiFi adaptors each connected to a different cameras. But what would be the proper network setting for that?
Mehmet Fide avatar
id flag
@A.B I use term "camera' because I found it easier to explain my problem with it. In reality they are special measurement props which stream real time measurement data through port 443. Sorry for that :) But the fact is same, they are not configurable, the manufacturer didn't think that someone will come and try to connect multiple probes from a single PC or MAC.
A.B avatar
cl flag
A.B
Using wireless really doesn't help because setup of wireless is more touchy than ethernet. Especially when considering using network namespaces. Are you able to succesfully use static IP addresses instead of DHCP to connect to the "cameras"? Or else are you able to manually configure wpa_supplicant? Can you provide the resulting wpa_supplicant configurations for your two devices? Is there currently a single wpa_supplicant process running, or two (one per device)?
A.B avatar
cl flag
A.B
Also does `iw phy phy0 |grep netns` 's answer include `* set_wiphy_netns` and are there two entries in /sys/class/ieee80211/ ?
A.B avatar
cl flag
A.B
Well I was curious and worked on the method not using network namespaces. network namespaces should be favored and give a more robust result, but I don't see how to make an answer with namespaces without having to ask the kind of questions I already asked above and more.
Score:3
cl flag
A.B

Presentation

This problem could be solved by using network namespaces, thus splitting the single Pi system into X routers doing NAT. That's what should be done. Alas I don't know how to write an answer that would not only have to include how to move the Wifi interfaces to a new network namespace (requires compatible drivers and iw phy phyX set netns ... instead of ip link set wlanX ... netns ...) but also especially their associated wpa_supplicant and DHCP client daemons with corresponding system integration tweaks. This requires good knowledge on how the specific system is configured with wireless and DHCP.

Instead this answer avoids using network namespaces and avoids having to reconfigure the handling of wpa_supplicant and the DHCP client: it uses policy routing.

Involving marks in policy routing is unavoidable for this case where the routing stack will only see destination port 443 rather than 4431/4432 (DNAT already changed it before). Marks will also be user to set conntrack (reply) zones to be sure to handle the case where multiple cameras assign the same IP address to their matching host interface.

Strict Reverse Path Forwarding (SRPF) will have to be relaxed to Loose RPF in case Strict was set by default, because ARP handling wont't receive the marks and can stay blocked.

As the cameras might not have set their default route to the client but might only have a LAN route, double NAT (source and destination) will also be done.

Setup

As OP didn't provide any eth0 setting, there's none here. The answer tries to not depend too much on this, but OP would have to adapt it if needed (especially if the 7 wireless interfaces won't all have their name starting with wlx).

Let's adjust the goal:

192.168.42.0/24 represents multiple overlapping IP networks that must not be reached directly to protect the outside clients from all possible routing complexity.

So the address 192.168.42.250 won't be used. Pi's visible address 192.168.0.205 will be used from the remote clients.

Any HTTPS access will get a bad certificate. Deal with it: I'm providing an answer based on tweaking network settings, but it won't include the setup of a reverse proxy to hide the certificate issue. Adding such reverse proxy also requires more network tweaks (added as an option at the end). Tests can be done from a client (but not the RPi) with:

curl --insecure https://192.168.0.205:4431/
curl --insecure https://192.168.0.205:4432/

Also to show some examples below, I took the case with both cameras having assigned the same IP address to the host so it appears on two interfaces, to raise the bar. It doesn't matter. Most of these settings must be done after all wireless connections are done rather than before. I won't deal on how to integrate this with the specific Linux OS handling it.

All commands should be run as root.

Examples are based on:

# ip route
default via 192.168.0.1 dev wlan0 
192.168.0.0/24 dev wlan0 proto kernel scope link src 192.168.0.205 
192.168.42.0/24 dev wlxb8b7f16a0602 proto kernel scope link src 192.168.42.10 metric 600 
192.168.42.0/24 dev wlxb8b7f16a04cd proto kernel scope link src 192.168.42.10 metric 600 

Routing rules to select additional routing tables that will isolate duplicate each camera LAN from the other camera LAN:

ip rule add fwmark 1 lookup 4431
ip rule add fwmark 2 lookup 4432

ip route add 192.168.42.0/24 dev wlxb8b7f16a0602 table 4431
ip route add 192.168.42.0/24 dev wlxb8b7f16a04cd table 4432

This makes routing work from client to cameras (if the RPi doesn't have a default route, examples below using 192.0.2.2 to test routes could use 192.168.0.101 instead):

# ip route get mark 2 from 192.0.2.2 iif wlan0 192.168.42.1
192.168.42.1 from 192.0.2.2 dev wlxb8b7f16a04cd table 4432 mark 2 
    cache iif wlan0 

but still not for replies if SRPF is enabled:

# ip route get mark 2 from 192.168.42.1 iif wlxb8b7f16a04cd 192.0.2.2
RTNETLINK answers: Invalid cross-device link

So an almost undocumented flag would have to be set on the camera interfaces:

sysctl -w net.ipv4.conf.wlxb8b7f16a0602.src_valid_mark=1
sysctl -w net.ipv4.conf.wlxb8b7f16a04cd.src_valid_mark=1

to get now:

# ip route get mark 2 from 192.168.42.1 iif wlxb8b7f16a04cd 192.0.2.2
192.0.2.2 from 192.168.42.1 via 192.168.0.1 dev wlan0 mark 2 
    cache iif wlxb8b7f16a04cd 

But actually, anyway ARP (from camera to host) is still disrupted when SRPF is set because ARP doesn't get iptables' marks.

So just use Loose RPF (rp_filter=2) instead (and then the setting for src_valid_mark above is not needed anymore) to solve it. This works whether RPF was disabled or set strict before:

sysctl -w net.ipv4.conf.wlxb8b7f16a0602.rp_filter=2
sysctl -w net.ipv4.conf.wlxb8b7f16a04cd.rp_filter=2

Add iptables rules setting marks to complete the routing part as well as deal with conflicting addresses in NAT later by setting the reply zone selector.

iptables -t raw -A PREROUTING ! -i wlx+ -p tcp --dport 4431 -j MARK --set-mark 1
iptables -t raw -A PREROUTING -i wlxb8b7f16a0602 -j MARK --set-mark 1
iptables -t raw -A PREROUTING -m mark --mark 1 -j CT --zone-reply 1

iptables -t raw -A PREROUTING ! -i wlx+ -p tcp --dport 4432 -j MARK --set-mark 2
iptables -t raw -A PREROUTING -i wlxb8b7f16a04cd -j MARK --set-mark 2
iptables -t raw -A PREROUTING -m mark --mark 2 -j CT --zone-reply 2

Add those rules to NAT to the target IP and port (which are always the same). The correct interface will then be chosen by the routing stack thanks to previous settings:

iptables -t nat -A PREROUTING ! -i wlx+ -p tcp -m mark ! --mark 0 -j DNAT --to-destination 192.168.42.1:443
iptables -t nat -A POSTROUTING -o wlx+ -j MASQUERADE

Should a 3rd interface called wlx3 be added, here are the steps. It can be generalized the same way for more:

Add a new ip rule selected with a new mark (3) that will use a new routing table (4433):

ip rule add fwmark 3 lookup 4433

Add the matching new routing table with its entry more or less duplicated from the main table LAN's route for the new interface:

ip route add 192.168.42.0/24 dev wlx3 table 4433

Loosen RPF on this interface if OS' defaults were SRPF (as told src_valid_mark isn't needed in the end):

sysctl -w net.ipv4.conf.wlx3.rp_filter=2

Choose a new port (4433) and add 3 new raw/PREROUTING iptables rules that include the new port, the new mark and the new interface:

iptables -t raw -A PREROUTING ! -i wlx+ -p tcp --dport 4433 -j MARK --set-mark 3
iptables -t raw -A PREROUTING -i wlx3 -j MARK --set-mark 3
iptables -t raw -A PREROUTING -m mark --mark 3 -j CT --zone-reply 3

(If the new interface name doesn't start with wlx add new nat rules accordingly.)

Here's an example of conntrack handling when a client connects twice, even using the same source port, to the two ports while the RPi got the very same IP address assigned to the two wlx wireless interfaces. The conntrack zone is included in flow selection and allows NAT to be handled correctly even if one side of the flows sees exactly the same addresses and ports:

# conntrack -E
    [NEW] tcp      6 120 SYN_SENT src=192.168.0.101 dst=192.168.0.205 sport=6666 dport=4431 [UNREPLIED] src=192.168.42.1 dst=192.168.42.10 sport=443 dport=6666 zone-reply=1
 [UPDATE] tcp      6 60 SYN_RECV src=192.168.0.101 dst=192.168.0.205 sport=6666 dport=4431 src=192.168.42.1 dst=192.168.42.10 sport=443 dport=6666 zone-reply=1
 [UPDATE] tcp      6 432000 ESTABLISHED src=192.168.0.101 dst=192.168.0.205 sport=6666 dport=4431 src=192.168.42.1 dst=192.168.42.10 sport=443 dport=6666 zone-reply=1 [ASSURED]
    [NEW] tcp      6 120 SYN_SENT src=192.168.0.101 dst=192.168.0.205 sport=6666 dport=4432 [UNREPLIED] src=192.168.42.1 dst=192.168.42.10 sport=443 dport=6666 zone-reply=2
 [UPDATE] tcp      6 60 SYN_RECV src=192.168.0.101 dst=192.168.0.205 sport=6666 dport=4432 src=192.168.42.1 dst=192.168.42.10 sport=443 dport=6666 zone-reply=2
 [UPDATE] tcp      6 432000 ESTABLISHED src=192.168.0.101 dst=192.168.0.205 sport=6666 dport=4432 src=192.168.42.1 dst=192.168.42.10 sport=443 dport=6666 zone-reply=2 [ASSURED]

Miscellaneous

  • misc 1

    For a camera to be able to ping the host or receive ICMP errors from the host, this (global) setting must be added:

    sysctl -w net.ipv4.fwmark_reflect=1
    

    else the ICMP answer doesn't follow policy routing. An other better way is to use CONNMARK/connmark, but it would make the answer unnecessarily more complex.

  • Misc 2

    The working result can't be tested correctly from the RPi itself but only from a client on the LAN (or on Internet with support from RPi's router). Settings are specific to the routing case.

    Optionally for the host to be able to work (and allowing a reverse proxy to be put in place), these additional settings can be added:

    Select the right interface even before NAT happens (requires kernel >= 4.17), else the socket will choose the wrong source address (of an other interface) later:

    ip rule add iif lo ipproto tcp dport 4431 lookup 4431
    ip rule add iif lo ipproto tcp dport 4432 lookup 4432
    

    The destination has to be DNATed in nat/OUTPUT. No need for the exact wlx name here, the correct outgoing route was already selected by the routing stack with the new routing rules (reply still requires part of iptables raw/PREROUTING rules from main answer). And a conntrack reply zone is also needed in raw/OUTPUT to handle the rare clash cases.

    iptables -t raw -A OUTPUT -o wlx+ -p tcp --dport 4431 -j MARK --set-mark 1
    iptables -t raw -A OUTPUT -m mark --mark 1 -j CT --zone-reply 1
    
    iptables -t raw -A OUTPUT -o wlx+ -p tcp --dport 4432 -j MARK --set-mark 2
    iptables -t raw -A OUTPUT -m mark --mark 2 -j CT --zone-reply 2
    
    iptables -t nat -A OUTPUT -p tcp -m mark ! --mark 0 -j DNAT --to-destination :443
    

    The tests in this case should be done from the RPi with:

    curl --insecure https://192.168.42.1:4431/
    curl --insecure https://192.168.42.1:4432/
    
  • misc 3

    The settings in misc 2 if adapted for local handling of UDP, for a different case than OP, would probably not be enough for some corner cases: UDP always needs support from the local application when in a multi-homed environment.

Score:1
id flag

I couldn't figure out how to do it with iptables but I solved the problem using socat worked nicely for me:

sudo socat TCP-LISTEN:443,interface=eth0,FORK TCP:192.168.42.1:443,interface=wlxb8b7f16a0602
sudo socat TCP-LISTEN:444,interface=eth0,FORK TCP:192.168.42.1:443,interface=wlxb8b7f16a04cd

All requests come to port 443 at eth0 interface will be redirected to 192.168.42.1:443 at wlxb8b7f16a0602 interface.

And similarly, requests come to port 444 at eth0 interface will be redirected to 192.168.42.1:443 at wlxb8b7f16a04cd interface.

A.B avatar
cl flag
A.B
Looks way simpler with a tool that can bind to an interface.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.