65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (7投票s)

2019年4月8日

CPOL

8分钟阅读

viewsIcon

17891

downloadIcon

103

奖励 - 使用 SlackBot 与您的 rPi 进行群聊

目录

引言

我们正在构建的内容由上图说明。

  1. 一个 4 rPi 的堆栈
  2. 一个 WiFi 到以太网的桥接器
  3. nginx 反向代理到每个 rPi

物理上看起来是这样的

想法是

  1. 给定域名(或本文中的路由器公共 IP:端口)...
  2. 通过 WiFi 将 TCP/IP 数据包路由到顶部的 rPi...
  3. 然后 nginx 通过以太网将其路由到 4 个 rPi 中的任何一个...
  4. 通过“DNS 伪装”,它用于实现 WiFi 到以太网的桥接。

DNS 伪装

我们使用 DNS 伪装创建 WiFi 到以太网的桥接。物理连接的 rPi 的 IP 地址将是 10.1.1.1 到 1.1.1.4。使用了两篇博客文章来弄清楚如何做到这一点

看来,自 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

  1. /bin/dotnet 中安装 dotnet
  2. 设置路径
  3. 创建一个名为“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] 选项时,现在有了区别

结论

这太棒了!一切都在按部就班地进行

  1. 路由器正在路由
  2. WiFi-以太网桥接器正在桥接
  3. nginx 正在进行反向代理
  4. 服务器正在提供服务!

我们还修改了我的 Slack Chat 应用程序,以便我们可以

  1. 向所有 rPi 广播命令
  2. 向单个 rPi 发送命令

虽然在设置域名、SSL 证书和带 SNI 的 ngnix 方面还有很多工作要做,但本文的目的是介绍如何迈出设置 rPI 堆栈的第一步,然后我们可以从中提供页面、提供“计算”能力、进行分布式数据实验等。

是时候休息一下了。

关于安装 .NET Core 的说明

这些说明是针对 .NET Core 2.0 的,我把它们放在这里,因为它们(我猜)不像“wget”命令那么晦涩,并且可能在 .NET Core 3.0 成熟时有用。

来自: https://blogs.msdn.microsoft.com/david/2017/07/20/setting_up_raspian_and_dotnet_core_2_0_on_a_raspberry_pi/

  • 运行 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 来测试安装。
© . All rights reserved.