我有 7 个摄像头,每个摄像头都充当 WiFi 接入点,我无法更改它们的配置。
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
从我的 Windows 笔记本,通过使用内部 WiFi 适配器,我可以连接到相机 1 的 ssid 并获取视频。然后我需要断开与它的连接,连接到相机 2 的 ssid 以从相机 2 获取视频,类似于 3、4..7。
我想要的是是从所有这些视频中同时获取视频。
我尝试过的: 我尝试将 7 个 USB WiFi 适配器插入我的笔记本电脑。每个适配器都配置为连接不同的摄像头。在这种情况下,Windows 显示 7 个不同的以太网接口,每个接口都从相应摄像头的 dhcp 服务器获取 IP。但所有摄像头都使用相同的 IP,即 192.168.42.1。此外,据我了解,Windows 支持多个 USB WiFi 适配器,但 MACOS 不支持。
我需要一种通用的解决方案来解决这个问题,到目前为止我还不知道该怎么做。非常感谢您的帮助和建议。
谢谢。
进一步测试: 我相信我快找到解决方案了。但仍然需要帮助。我拿了一个运行 Ubuntu 的 Raspberry Pi 4。我打算将它用作路由器。默认情况下,PI 硬件带有 2 个以太网接口;
eth0
-> 1Gbit 电缆连接wlan0
-> 嵌入式 WiFi 接口
我插入了两个额外的 USB WiFi 适配器,现在它有两个以太网接口,分别名为wlxb8b7f16a0602和wlxb8b7f16a04cd。每个 USB WiFi 适配器连接到不同的摄像头。输出如下ifconfig
:
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
在这种配置中;
eth0
-> 未连接wlan0
-> 连接到我的互联网调制解调器(仅用于 ssh 到 pi)wlxb8b7f16a0602
-> 连接到 Camera1wlxb8b7f16a04cd
-> 已连接到 Camera2
尽管每个摄像机都有相同的 IP 192.168.42.1,但由于它们连接到不同的接口,我可以使用-I
如下参数成功 ping 它们:
对于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
对于 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
从这里,假设我为我的 eth0 接口分配一个静态 IP,即 192.168.42.250
我想转发来自
- 192.168.42.250:443在 eth0到192.168.42.1:443 位于wlxb8b7f16a0602
- 192.168.42.250:444在 eth0到192.168.42.1:443 位于wlxb8b7f16a04cd
如果您能帮助我解决这剩下的一点,我会接受您的回答。
致@AB:
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/
答案1
推介会
这个问题可以通过使用网络命名空间来解决,从而将单个 Pi 系统拆分为执行 NAT 的 X 个路由器。这就是应该做的。唉,我不知道如何写一个答案,它不仅必须包括如何将 Wifi 接口移动到新的网络命名空间(需要兼容的驱动程序而iw phy phyX set netns ...
不是ip link set wlanX ... netns ...
)但尤其其相关wpa_supplicant
和 DHCP 客户端守护程序以及相应的系统集成调整。这需要对特定系统如何配置无线和 DHCP 有很好的了解。
相反,这个答案避免使用网络命名空间,并避免重新配置处理wpa_supplicant和 DHCP 客户端:它使用策略路由。
在这种情况下,在策略路由中不可避免地会涉及标记,因为路由堆栈将只看到目标端口 443,而不是 4431/4432(DNAT 之前已经更改了它)。标记还将用于设置 conntrack(回复)区域,以确保处理多个摄像头将相同 IP 地址分配给其匹配主机接口的情况。
严格反向路径转发(SRPF)必须轻松到松散的 RPF如果默认设置了“严格”,则因为 ARP 处理不会接收标记并且可以保持阻止状态。
由于摄像机可能没有设置到客户端的默认路由,而可能只有 LAN 路由,因此也会进行双 NAT(源和目标)。
设置
由于 OP 没有提供任何eth0设置,这里没有。答案尽量不要过多地依赖于此,但如果需要,OP 必须对其进行调整(尤其是如果 7 个无线接口的名称不都以 开头wlx
)。
我们来调整一下目标:
192.168.42.0/24 代表多个重叠的 IP 网络,这些网络不能直接到达,以保护外部客户端免受所有可能的路由复杂性的影响。
因此不会使用地址 192.168.42.250。远程客户端将使用 Pi 的可见地址 192.168.0.205。
任何 HTTPS 访问都会得到一个坏证书。处理它:我提供了一个基于调整网络设置的答案,但它不包括设置反向代理来隐藏证书问题。添加这样的反向代理还需要更多的网络调整(最后添加为一个选项)。可以从客户端(但不是 RPi)进行测试:
curl --insecure https://192.168.0.205:4431/
curl --insecure https://192.168.0.205:4432/
另外,为了在下面展示一些示例,我采用了两个摄像头都为主机分配了相同 IP 地址的情况,因此该地址出现在两个接口上,以提高标准。这没关系。大多数这些设置必须在所有无线连接完成后完成,而不是之前完成。我不会讨论如何将其与处理它的特定 Linux 操作系统集成。
所有命令都应以 root 身份运行。
示例基于:
# 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
路由规则用于选择额外的路由表,将每个摄像机 LAN 与其他摄像机 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
这使得从客户端到摄像机的路由工作(如果 RPi 没有默认路由,下面使用 192.0.2.2 测试路由的示例可以改用 192.168.0.101):
# 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
但如果启用了 SRPF,则仍然不会回复:
# ip route get mark 2 from 192.168.42.1 iif wlxb8b7f16a04cd 192.0.2.2
RTNETLINK answers: Invalid cross-device link
因此几乎没有记录的旗帜必须在相机接口上设置:
sysctl -w net.ipv4.conf.wlxb8b7f16a0602.src_valid_mark=1
sysctl -w net.ipv4.conf.wlxb8b7f16a04cd.src_valid_mark=1
现在得到:
# 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
但实际上,反正设置 SRPF 后,ARP(从摄像机到主机)仍然中断,因为 ARP 没有获得 iptables 的标记。
因此,只需使用松散 RPF ( rp_filter=2
)(然后src_valid_mark
不再需要上述设置)即可解决该问题。无论之前是否禁用 RPF 或将其设置为严格,此方法均有效:
sysctl -w net.ipv4.conf.wlxb8b7f16a0602.rp_filter=2
sysctl -w net.ipv4.conf.wlxb8b7f16a04cd.rp_filter=2
添加iptables规则设置标记,完成路由部分,以及稍后通过设置答复区域选择器来处理NAT中的冲突地址。
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
将这些规则添加到 NAT 到目标 IP 和端口(始终相同)。然后,路由堆栈将根据之前的设置选择正确的接口:
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
如果要添加第三个接口(称为 wlx3),请按以下步骤操作。可以按照相同的方式推广到更多接口:
添加一个用新标记 (3) 选择的新 IP 规则,该规则将使用新的路由表 (4433):
ip rule add fwmark 3 lookup 4433
添加匹配的新路由表,其条目或多或少与新接口的主表 LAN 路由重复:
ip route add 192.168.42.0/24 dev wlx3 table 4433
如果操作系统的默认设置是 SRPF,则放宽此接口上的 RPF(因为src_valid_mark
最后说不需要):
sysctl -w net.ipv4.conf.wlx3.rp_filter=2
选择一个新的端口(4433)并添加 3 个新的 raw/PREROUTINGiptables包含新端口、新标记和新接口的规则:
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
(如果新接口名称不是以wlx
add new纳特规则另行规定。
以下是一个例子连接跟踪当客户端使用相同的源端口两次连接到两个端口时,RPi 会为两个 wlx 无线接口分配相同的 IP 地址。连接跟踪区域包含在流选择中,即使流的一侧看到完全相同的地址和端口,也可以正确处理 NAT:
# 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]
各种各样的
杂项 1
为了使摄像机能够 ping 主机或从主机接收 ICMP 错误,必须添加此(全局)设置:
sysctl -w net.ipv4.fwmark_reflect=1
杂项 2
无法从 RPi 本身正确测试工作结果,只能从 LAN 上的客户端(或在 RPi 路由器支持的 Internet 上)测试。设置特定于路由情况。
为了使主机能够工作(并允许建立反向代理),可以添加以下附加设置:
在 NAT 发生之前选择正确的接口(需要内核 >= 4.17),否则套接字稍后将选择错误的源地址(其他接口的地址):
ip rule add iif lo ipproto tcp dport 4431 lookup 4431 ip rule add iif lo ipproto tcp dport 4432 lookup 4432
目的地必须在 nat/OUTPUT 中进行 DNAT。这里不需要确切的 wlx 名称,路由堆栈已经使用新路由规则选择了正确的传出路由(回复仍然需要主答案中的 iptables raw/PREROUTING 规则的一部分)。并且连接跟踪raw/OUTPUT 中还需要回复区来处理罕见的冲突情况。
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
在这种情况下,测试应该从 RPi 进行:
curl --insecure https://192.168.42.1:4431/ curl --insecure https://192.168.42.1:4432/
杂项 3
中的设置杂项 2如果适用于本地处理 UDP,对于与 OP 不同的情况,可能不足以应对某些特殊情况:在多宿主环境中,UDP 始终需要本地应用程序的支持。
答案2
我不知道该怎么做iptables
,但我用socat
对我来说很有效的方法解决了这个问题:
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
所有请求都到达港口443在eth0接口将被重定向到192.168.42.1:443在wlxb8b7f16a0602界面。
同样,请求到达端口444在eth0接口将被重定向到192.168.42.1:443在wlxb8b7f16a04cd界面。