带 WiFi-以太网桥接和 nginx 反向代理的 4 堆 rPi 集群






4.91/5 (7投票s)
奖励 - 使用 SlackBot 与您的 rPi 进行群聊
目录
引言
我们正在构建的内容由上图说明。
- 一个 4 rPi 的堆栈
- 一个 WiFi 到以太网的桥接器
- nginx 反向代理到每个 rPi
物理上看起来是这样的
想法是
- 给定域名(或本文中的路由器公共 IP:端口)...
- 通过 WiFi 将 TCP/IP 数据包路由到顶部的 rPi...
- 然后 nginx 通过以太网将其路由到 4 个 rPi 中的任何一个...
- 通过“DNS 伪装”,它用于实现 WiFi 到以太网的桥接。
DNS 伪装
我们使用 DNS 伪装创建 WiFi 到以太网的桥接。物理连接的 rPi 的 IP 地址将是 10.1.1.1 到 1.1.1.4。使用了两篇博客文章来弄清楚如何做到这一点
- 2017/5/8: https://pimylifeup.com/raspberry-pi-wifi-bridge/
- 2018/4/14: https://willhaley.com/blog/raspberry-pi-wifi-ethernet-bridge/
看来,自 2017 年以来,dnsmasq 的配置方式发生了一些变化。大多数步骤(除了创建静态无线 IP,这破坏了我的 rPI 上的无线连接)关于初始设置都没问题。对于其余的 dnsmasq 步骤(特别是配置文件),我不得不遵循 2018 年博客文章中的步骤。
步骤
执行这些命令以使所有内容保持最新并安装 dnsmasq
。
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install dnsmasq
验证您的 WiFi 是否已设置。此文件应包含内容
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
如果不是,请运行 raspi-config
,即使您的 rPi 可能已设置为使用 Wifi,也要从无线配置菜单选项(可能再次)配置您的 WiFi。
编辑: sudo nano /etc/sysctl.conf
并取消注释(删除 '#
')行 #net.ipv4.ip_forward=1
运行这些命令
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
上述命令(我能弄清楚并且应该很明显)将 wlan0
转发到 eth0
,将 eth0
转发到 wlan0
。然后保存配置文件,并使用以下命令,在 rPi 启动时恢复
编辑 sudo nano /etc/rc.local
并在 exit 0
之前添加行 iptables-restore < /etc/iptables.ipv4.nat
。
创建 /etc/network/interfaces.d/eth0 并包含
auto eth0
allow-hotplug eth0
iface eth0 inet static
address 10.1.1.1
netmask 255.255.255.0
gateway 10.1.1.1
创建 /etc/dnsmasq.d/bridge.conf 并包含
interface=eth0
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=10.1.1.2,10.1.1.254,12h
重启。尝试这些命令
ifconfig
您应该看到(您的无线 IP 很可能不同)
eth0: flags=4163<up,broadcast,running,multicast> mtu 1500
inet 10.1.1.1 netmask 255.255.255.0 broadcast 10.1.1.255
...
wlan0: flags=4163<up,broadcast,running,multicast> mtu 1500
inet 192.168.0.15 netmask 255.255.255.0 broadcast 192.168.0.255
</up,broadcast,running,multicast></up,broadcast,running,multicast>
另外执行
sudo iptables -L
您应该会看到:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
如果没有,请回顾上面的步骤和文章链接。如果一切正常,您可以将设备连接到以太网集线器。
速度测试
笔记本 WiFi
笔记本连接到 rPi WiFi-以太网桥接器
奇怪的是,当我前一天晚上进行测试时,rPi WiFi-以太网桥接器速度更快。谁知道呢。
为每个 rPI
这些步骤应该为每个 rPi 执行,因为它比连接四个显示器、键盘和鼠标,或者经常来回移动电缆要容易得多。
启用 SSH
使用 raspi-config
为每个 rPI 启用 SSH
sudo raspi-config
这会打开一个简单的 UI
导航到项目 5“接口选项”
选择“P2 SSH - 使用 SSH 启用/禁用对您的 Pi 的远程命令行访问”
在提示“您想启用 SSH 服务器吗?”时选择“是”
选择“确定”
选择“完成”以退出配置应用程序。
在此处阅读更多关于 raspi-config 应用程序的内容: 此处。
安装 .NET Core 2.2
我将使用 .NET Core 和 C# 进行开发,所以让我们在所有四个 rPI 上安装这个
wget <a href="https://download.visualstudio.microsoft.com/download/pr/
36bff52b-2cdd-4011-8e92-d00f7537704f/9885ba267b1ef29a1401adc387d9a016/
dotnet-sdk-2.2.101-linux-arm.tar.gz">https://download.visualstudio.microsoft.com/
download/pr/36bff52b-2cdd-4011-8e92-d00f7537704f/9885ba267b1ef29a1401adc387d9a016/
dotnet-sdk-2.2.101-linux-arm.tar.gz</a>
sudo mkdir -p /bin/dotnet && sudo tar zxf dotnet-sdk-2.2.101-linux-arm.tar.gz -C /bin/dotnet
export DOTNET_ROOT=/bin/dotnet
export PATH=$PATH:/bin/dotnet
sudo ln -s /bin/dotnet/dotnet /usr/local/bin
这
- 在 /bin/dotnet 中安装 dotnet
- 设置路径
- 创建一个名为“
dotnet
”的符号链接(快捷方式)
设置其他 3 个 rPI
我们现在可以使用 wifi-ethernet 链接来设置其他 rPI,而无需在它们上启用 WiFi!
静态 IP
我希望我的 rPI 拥有静态 IP。顶部的 rPI 是 10.1.1.1,所以接下来的三个应该是 .2 到 .4 是很自然的。通过编辑 /etc/dhcpcd.conf 并找到以下部分,取消注释配置并相应地设置 IPv4 地址,可以轻松完成此操作
# Example static IP configuration:
interface eth0
static ip_address=10.1.1.2/24
static ip6_address=fd51:42f8:caae:d92e::ff/64
static routers=10.1.1.1
static domain_name_servers=10.1.1.1 8.8.8.8 fd51:42f8:caae:d92e::1
重启,运行 ifconfig
,并验证静态 IP 地址
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.1.1.2 netmask 255.255.255.0 broadcast 10.1.1.255
在 WiFi 网桥 rPi 上安装
我已经在 此处 更详细地写了以下部分,所以这只是一个快速的“执行此操作”步骤。这些步骤是在 WiFi-以太网桥接器设置的任何 rPI(在本例中为顶部的 rPI)上执行的。
安装 PuTTY
在 10.1.1.1 上安装 PuTTY,以便我们可以与 .1、.2、.3 和 .4 上的其他 rPI 通信(是的,即使这在“设置其他 3 个 rPI”部分下,也要为 .1 执行此操作)。
sudo apt-get install -y putty
安装 nginx
我将在 .1 上安装 nginx,目的是让它将公共 WiFi 地址端口路由到负责提供网站的特定 rPI——每个 rPI 一个网站。
安装 nginx
sudo apt-get install nginx
开机自动启动 nginx
cd /etc/init.d
sudo update-rc.d nginx defaults
重启并在 rPI 桌面上的 Chromium 浏览器中打开,或者从通过以太网连接到集线器的笔记本电脑打开,然后导航到 http://10.1.1.1。
路由器端口转发和 nginx 设置
接下来,我们希望将 WiFi 地址端口转发到每个以太网地址。我将这样配置我的路由器
3001-3004 是入站端口,8081-8084 是我们希望 nginx 拦截并路由到 10.1.1.1-4 的端口。这主要是为了测试。在“现实世界”中,我将设置一个或多个域名,路由器会将端口 80(HTTP)和端口 443(HTTPS)路由到充当 WiFi-以太网桥接器的 rPI,使用授权的 SSL 证书和 SNI 将域名路由到相应的 rPI。nginx 还可以将特定的 URL 路径路由到不同的 rPI,因此可以创建一个设置,其中不同的页面由不同的 rPI 处理,但这超出了本文“概念验证”的范围。
配置 nginx
考虑到上述路由器配置,每个暴露给公众的端口都被路由到一个特定的 rPI。这是添加到 nginx /etc/nginx/sites-available/default 文件的路由声明
server {
listen 8081;
location / {
proxy_pass http://10.1.1.1:8080;
}
}
server {
listen 8082;
location / {
proxy_pass http://10.1.1.2:8080;
}
}
server {
listen 8083;
location / {
proxy_pass http://10.1.1.3:8080;
}
}
server {
listen 8084;
location / {
proxy_pass http://10.1.1.4:8080;
}
}
使用以下命令重新加载 nginx
sudo /etc/init.d/nginx reload
使用 dotnet-serve 进行测试
通过在其中一个 rPI(我选择了第 4 个)上安装 dotnet-serve 来进行测试
dotnet tool install --global dotnet-serve
然后运行
export PATH="$PATH:/home/pi/.dotnet/tools"
export DOTNET_ROOT=/bin/dotnet
dotnet-serve -a 10.1.1.[rPI IP address]
导出对于查找 dotnet-serve 和让 dotnet-serve 找到依赖库是必要的。
例如,我堆栈中的第 4 个 rPI,最终命令是
dotnet-serve -a 10.1.1.4
出于某种原因,当我尝试指定端口 80 时,我收到访问被拒绝的错误,这就是为什么上面 nginx 配置的是端口 8080。
查找您的公共 IP 并输入
http://[your public ip]:3004
您应该会收到
并且 dotnet-serve 应该显示
您可以浏览文件夹并下载 MagPi PDF!
使用 Slack 广播命令
在我的文章《使用 Slack 与您的 rPi 聊天》中,我使用 Slack 与单个 rPi 进行通信。我们可以使用 Slack 向堆栈中的所有 rPi 发出命令。这对于执行关闭或重启所有 rPi 等操作非常有用!
将 slackbot\bin\Debug\netcoreapp2.2\linux-arm\publish 文件夹内容通过 WinSCP 传输到每个 rPI 后,将 slackBot
文件更改为可执行文件(只需执行一次),然后运行它
chmod +755 ./slackBot
./slackBot
对每个 rPI 执行此操作。现在,在您的 Slack 频道中 ping rpi
所有四个都响应了!
让我们看看每个 rPi 的内存利用率
当然,我们想知道哪个 rPi 在报告,因为它们不一定按顺序排列。通过使用 C# slackBot 应用程序中执行的 bash 脚本来获取 eth0 地址,我们可以报告响应的 rPi。
static void GetIPAddress()
{
ipAddress = "ifconfig eth0 | grep \"inet \"".Bash().Trim().
RightOf("inet").LeftOf("netmask").Trim();
Console.WriteLine($"IP: {ipAddress}");
}
然后,我们可以将此地址添加到 rPi 发送到 Slack 频道的每个消息的前面
...
if (router.TryGetValue(cmd, out Func<string, List<string>, string> fnc))
{
ret = ipAddress + ": " + fnc(data, options);
}
else
{
// Try as bash command.
string cmdline = (cmd + " " + data).Trim();
ret = $"```\r\n{ipAddress}\r\n{cmdline.Bash()}```";
}
...
结果很不错
或者,对于 bash 命令,这里是一个带有 rPi IP 地址的示例输出
当然,与特定 rPI 对话也很好。我们将通过添加 rPI IP 地址的最后一位数字作为选项(使用“--
”语法)来仅与其中一个对话。在消息接收处理程序中,我们检查 --[ddd]
,其中 [ddd]
是 IP 地址最后部分的数字
...
while (cmd.StartsWith("--"))
{
var opt = cmd.LeftOf(" ");
// Check if a specific address [n] in our IP x.y.z.n is specified.
// If that's not our address, just exit now.
if (opt.Length > 2 && char.IsDigit(opt[2]))
{
if (opt.Substring(2) != ip4thDigits)
{
return;
}
}
options.Add(opt);
cmd = message.text.RightOf(opt).Trim().LeftOf(" ");
}
请注意,当我们使用 --[ddd]
选项时,现在有了区别
结论
这太棒了!一切都在按部就班地进行
- 路由器正在路由
- WiFi-以太网桥接器正在桥接
- nginx 正在进行反向代理
- 服务器正在提供服务!
我们还修改了我的 Slack Chat 应用程序,以便我们可以
- 向所有 rPi 广播命令
- 向单个 rPi 发送命令
虽然在设置域名、SSL 证书和带 SNI 的 ngnix 方面还有很多工作要做,但本文的目的是介绍如何迈出设置 rPI 堆栈的第一步,然后我们可以从中提供页面、提供“计算”能力、进行分布式数据实验等。
是时候休息一下了。
关于安装 .NET Core 的说明
这些说明是针对 .NET Core 2.0 的,我把它们放在这里,因为它们(我猜)不像“wget
”命令那么晦涩,并且可能在 .NET Core 3.0 成熟时有用。
- 运行 sudo apt-get install curl libunwind8 gettext。这将使用 apt-get 包管理器安装三个先决包。
- 运行 curl -sSL -o dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Runtime/release/2.0.0/dotnet-runtime-latest-linux-arm.tar.gz 下载适用于 ARM32 的最新 .NET Core Runtime。这在 Daily Builds 页面上被称为 armhf。
- 运行 sudo mkdir -p /opt/dotnet && sudo tar zxf dotnet.tar.gz -C /opt/dotnet 以创建目标文件夹并将下载的包解压到其中。
- 运行 sudo ln -s /opt/dotnet/dotnet /usr/local/bin` 设置符号链接……对于 Windows 用户来说,这是一个快捷方式 😉 指向 dotnet 可执行文件。
- 通过键入
dotnet --help
来测试安装。