几天来,我一直在尝试设置我的 Ubiquiti ErPoe-5(固件 1.9.1)以使用 nginx 运行反向代理,但似乎大多数麻烦都是由于我无法在设备上获取最新版本的 nginx 造成的。
这教程我看到在其上安装 nginx 只能达到 nginx 1.2,它不支持 websockets 或 HTTP2。HTTP2 不是必需的,但对于我想要通过反向代理公开的内部资源,websockets 支持是必须的。事实上,路由器本身在自己的 Web 管理界面中使用它们,而且从ubiquiti 论坛上的这篇文章您可能也需要 HTTP2。
答案1
笔记:升级到固件 2.x 或更高版本将允许您使用新的 Stretch 存储库,如问题中链接的教程Stretch 存储库将 nginx 包更新为 1.10,支持 websockets 和 HTTP2。但是,以下步骤和脚本在 2.x 下仍然适用,因此答案不会更新以反映新的固件/包版本,以避免任何不想升级到 2.x 固件的人产生混淆(固件的初始版本给早期采用者带来了一些麻烦,并且 2.x 固件版本中仍然存在已知的性能下降问题)。
笔记2:本回答假设您具有足够的常见 Linux 命令知识和/或至少能够通过 SSH 登录路由器。如果没有,那么在继续之前,您应该先复习一下技能,以满足这些先决条件,因为我不打算在本回答或后续评论中介绍 Linux 脚本或命令的基础知识。
背景信息和免责声明(1.2 是安全的,但 1.14 可以运行)
在固件 2.x 版本发布之前,Ubiquiti 路由器基于 Debian 7.11(即 wheezy),因此,在不违反规范的情况下,您能获得的最佳版本是 nginx 1.6(通过使用存储库wheezy-backports
而不是或除了wheezy
)。这将适用于 websocket 支持,但像 http2 这样的新选项仍然缺失。
要获得较新的版本(例如 1.14),您必须走出舒适区并开始使用较新的 Debian 9.5 存储库 - 即和stretch
。stretch-backports
我说“走出舒适区”不是因为糟糕的体验,而是因为逻辑表明 Ubiquiti 在路由器上使用 2.x 之前的固件版本可能有原因。因此,当软件包依赖于升级路由器可能正在使用的其他软件包(即 libc6)时,wheezy
使用软件包会存在一定风险。stretch
因此,虽然我不能说下面的解决方案不会破坏路由器上的任何功能,但我可以说我使用了相当多的路由器功能(包括 openvpn 服务器/客户端、负载平衡和 VLAN),并且没有遇到任何问题。
我还能够成功地重新刷新当前版本的 Ubiquiti EdgeMax OS/固件(2.0.8),没有任何问题,将所有软件包恢复为它们的库存/默认版本。(但请注意,重新刷新固件也会清除您所做的任何未存储在目录中的调整/自定义/config
- 始终将它们存储在/config
某个地方,然后添加一个启动脚本,以便/config/scripts/post-config.d
在需要时在其他位置维护与它们的链接)
因此,我可以很放心地说,这次安装后,未来的 Ubiquiti 更新可能会顺利安装 - 尽管您必须重新安装 nginx(可能使用下面的脚本)。
现在已经不再需要通常的免责声明,下面是对我有用的方法。
我的解决方案(打破规则并获得 1.14)
安全第一
备份你的配置。
如果你已经尝试安装 nginx,那么继续安装也是个好主意重新安装最新固件只是为了让一切回到一个良好的基点(如果您在通常的 CLI 配置或 Web 界面选项之外进行了任何调整/自定义,请小心 - 您可能会丢失它们)。
由于你将要修改驱动 Web 界面的服务,因此熟悉从 SSH 刷新固件更新所需的命令以及(提示:)
add system image https://dl.ui.com/firmwares/edgemax/v1.10.x/ER-e100.v1.10.10.5210345.tar
。
现在是有趣的部分
通过 SSH* 进入您的路由器并运行以下脚本(或等效语句),它将:
- 设置适当的 Debian 存储库(
stretch
和stretch-backports
) - 将存储库优先级设置为优先
stretch-backports
(如果您想使用 nginx 1.10.3,则修改下面的脚本为优先,stretch
而不是stretch-backports
将其从优先级 - 910 中删除) - 配置一个启动脚本,用于在每次系统启动时创建 nginx 日志目录(否则路由器重启时 nginx 将无法启动)
- 下载/安装最新稳定版本nginx-light包(撰写本文时为 1.14.0)。
* 你应该不是使用 Web 界面中的 CLI 功能来替代 SSH,因为 Web 界面可能会在该过程中暂时无法运行。
#! /bin/bash
vcfg=/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper
echo Updating package repositories ...
echo
$vcfg begin
$vcfg delete system package
$vcfg set system package repository stretch url http://http.us.debian.org/debian
$vcfg set system package repository stretch components "main contrib non-free"
$vcfg set system package repository stretch distribution stretch
$vcfg set system package repository stretch-backports url http://http.us.debian.org/debian
$vcfg set system package repository stretch-backports components "main contrib non-free"
$vcfg set system package repository stretch-backports distribution stretch-backports
$vcfg commit
$vcfg end
apt-get update
echo
echo Setting repository priorities ...
echo
echo "Package: *
Pin: release a=stretch
Pin-Priority: 900
Package: *
Pin: release a=stretch-backports
Pin-Priority: 910">/etc/apt/preferences.d/stretch
echo
echo Temporarily stopping the current web interface ...
echo
kill -SIGTERM $(cat /var/run/lighttpd.pid)
echo
echo Installing nginx-light ...
echo
echo "#! /bin/bash
[ -d /var/log/nginx ] || mkdir /var/log/nginx">/config/scripts/post-config.d/create_nginx_log_dir
chmod a+x /config/scripts/post-config.d/create_nginx_log_dir
[ -d /var/log/nginx ] || mkdir /var/log/nginx
apt-get install nginx-light -V -y
echo
echo Restarting the old web interface ...
echo
service nginx stop
/usr/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
echo
echo Updating the nginx default site listen on non-standard ports ...
echo
sed -i -E 's/^(\s*)(listen\s+(:|\[|\])*)([0-9]+)(;|\s)/\1\2\4\4\5/g' /etc/nginx/sites-enabled/default
echo
echo Starting the nginx service ...
echo
service nginx start
echo
echo Installation complete.
Enter[对于重新启动服务的提示回答“y ” ]
现在您应该已经安装好了 nginx,并且应该能够通过http://<router IP address>:8080
Web 浏览器导航到 来测试它。请注意,应该通过上述脚本中的命令8080
配置使用端口,而不是默认端口,因为默认端口可能会与您的默认路由器 Web 界面冲突。sed
80
nginx 是否会作为路由器的反向代理?
lighttpd
我个人更喜欢为路由器上默认提供的服务/GUI使用非标准端口(下面示例配置中的 553) ,然后使用 nginx(监听标准端口 80/443)作为反向代理lighttpd
。这样我就可以为包括路由器在内的所有本地网络网站使用一个域名(即 router.myhouse.com、nas.myhouse.com 等)。如果您希望执行相同操作,可以使用语句更改 GUI 端口configure -> set service gui http(s)-port ###
,或在Config Tree
Web 界面/GUI 部分进行相同更改。
使用反向代理配置文件配置 nginx
接下来,您需要将 nginx 配置为某些资源的反向代理。通常,这将是一个本地网络资源,可通过在 URL 中使用特定主机/域名来访问,该 URL 解析为路由器的 nginx 监听端口。
为此,您可以在/etc/nginx/sites-enabled
目录中创建一个 nginx 配置文件(或者更好的是在目录下创建它/config/user-data
,然后在目录下创建指向该文件的链接/etc/nginx/sites-enabled
- 这将使从重置/etc
目录内容的升级中恢复变得更容易)。
网上有很多 nginx 配置文件的示例,但如果您打算将路由器接口(或其他使用 websockets 的网站)放在 nginx 反向代理后面,那么下面的示例可能会很有用。或者如果您专门想将 Synology NAS 放在它后面(特别是照片站有点棘手)。
upstream edgemax {
server 192.168.1.1:553;
keepalive 32;
}
upstream nas {
server 192.168.1.7:5001;
keepalive 32;
}
upstream nasphoto {
server 192.168.1.5:443;
keepalive 32;
}
upstream nasfile {
server 192.168.1.7:7001;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name router.*;
ssl_certificate /config/user-data/ssl_chain_key.pem;
ssl_certificate_key /config/user-data/ssl_chain_key.pem;
client_max_body_size 0;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass https://edgemax;
}
}
server {
listen 443 ssl http2;
server_name nas.*;
ssl_certificate /config/user-data/ssl_chain_key.pem;
ssl_certificate_key /config/user-data/ssl_chain_key.pem;
client_max_body_size 0;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
location / {
proxy_pass https://nas;
}
location /photo {
proxy_pass https://nasphoto/photo;
}
}
server {
listen 443 ssl http2;
server_name files.*;
ssl_certificate /config/user-data/ssl_chain_key.pem;
ssl_certificate_key /config/user-data/ssl_chain_key.pem;
client_max_body_size 0;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
location / {
proxy_pass https://nasfile;
}
}
server {
listen 443 ssl http2;
server_name photos.*;
ssl_certificate /config/user-data/ssl_chain_key.pem;
ssl_certificate_key /config/user-data/ssl_chain_key.pem;
client_max_body_size 0;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
rewrite ^/photo/(.*)$ /$1;
location / {
proxy_pass https://nasphoto/photo/;
}
}
一旦反向代理配置文件到位,您就可以运行sudo service nginx restart
以使其生效。/var/log/nginx/error.log
如果有问题,请参阅。
提示1:如果您计划为 nginx 反向代理使用非标准端口(即,您的反向代理配置中除了listen 80
and/or之外的内容listen 443
),那么最好将proxy_set_header Host $host;
上述配置替换为proxy_set_header Host $http_host;
。这对于 websocket 尤其重要,因为 websocket 似乎总是希望让 web 客户端从默认端口请求流量,否则会导致接口缺少组件或实时数据。(您也可以尝试proxy_set_header Host $host:$server_port;
,但请注意,这截然不同,因为它总是会将端口添加到标头,即使在原始请求中未使用端口)
提示 #2:还请注意,其用法server_name router.*
仅表示使用 URLrouter.<anything>.<anything>
浏览 nginx 反向代理将导致配置的该部分被应用。(您会发现大多数示例都使用完整/显式域名,如router.domain.com
)
这不仅对于可能更改域名/dns 名称(即,适用于router.home.com
不router.home.net
更改配置的情况)很有用,而且还有助于保持server_name
条目简短。这很重要,因为使用长名称通常会导致在启动 nginx 时出现类似“增加存储桶大小”的错误。如果您必须使用长名称,那么您可能需要调整服务器名称哈希值最大大小和/或server_names_hash_bucket_size在您的配置中。
更新:
我已成功将路由器从 EdgeOS 1.9.1 版更新至 2.0.9-hotfix2 版(包括 2.0.9-hotfix2)之间的所有版本,且基本没有出现任何问题。更新后路由器上没有 nginx(如预期),但我能够运行我的脚本(此答案中的第一个代码块),它马上就恢复了。保持自定义设置,/config
并使用脚本来/config/scripts/post-config.d
维护重启/升级后无法保留的任何更改,这是顺利完成的关键。
更新 #2:
此过程也适用于 ER-X 等小型路由器。但是,由于设备上的可用存储空间有限,您将被迫删除非活动固件映像,以便为 nginx 腾出空间。每次更新后也需要执行此操作。要删除非活动固件映像,请运行delete system image
并对提示回答“是”。
-- 我的 ER-X 更新过程 --
- 备份我的配置!!!!
- 更新到最新固件并重启(并验证除 nginx 之外的基本功能)
- 使用命令删除旧固件(现在是非活动映像)
delete system image
(show system storage
删除前报告使用率为 67%,删除后报告使用率为 33%) - 验证外部 ping 是否有效(ping 8.8.8.8),如果无效,请重新启动路由器。这是最近固件版本中的一个已知问题,与此过程或所用脚本无关。
- 使用上述脚本/步骤重新安装 nginx(
show system storage
安装后报告使用率为 67%) - 运行
sudo apt-get clean
以释放临时文件等使用的空间(show system storage
报告清理后使用率为 52%)