侧边栏壁纸
  • 累计撰写 270 篇文章
  • 累计创建 141 个标签
  • 累计收到 16 条评论

目 录CONTENT

文章目录

群晖 NAS 之 Docker Nginx 反向代理

Sherlock
2019-03-20 / 0 评论 / 0 点赞 / 23896 阅读 / 0 字
温馨提示:
本文最后更新于2023-11-10,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

近期给NAS配备了一个公网IP(使用公网ip盒子,此处不细说了)

诉求:利用 Docker 容器中的 Nginx 实现多域名访问不同应用、或者单域名不同文根访问不同应用,规避IP+端口访问。

1.准备

需要先在 Docker 中下载 Nginx 镜像(国内Docker hub网站支持不好,可再注册表配置中配置阿里云注册表镜像服务,服务地址可从阿里云容器镜像服务控制台获取)。

2.修改掉群晖自带 Nginx 默认占用的 80 端口

我们知道 Synology DSM 默认使用端口5000 (http)和5001 (https),但它的 Nginx 进行重定向 占用了端口 80 。例如,Photo Station 就使用了 80 端口(https对应的为:443)。

群晖不提供可修改端口的UI界面(因为他根本就不希望我们使用80端口),我们需要进入SSH,更改一些系统文件。

群晖每次运行自带nginx时,会根据模板文件,重新生成配置文件,位置在
/etc/nginx/app.d -> /var/tmp/nginx/app.d(软链接指向临时目录),所以我们修改这个文件意义是不大的,需要直接修改模板文件(倒是可以参考其配置设置我们的 https 转发)。

进入cd /usr/syno/share/nginx目录,修改 server.mustacheDSM.mustacheWWWService.mustache 这三个配置文件(使用 root 账号,sudo -i)。

Mustache是一种简单的模板语言,及时我们对他不够了解,也并不影响我们的修改工作。
升级DSM后可能会被覆盖==(暂不确定,要注意下)==。

使用编辑器打开,会发现服务器默认配置如下所示:

server {
    listen 80 default_server{{#reuseport}} reuseport{{/reuseport}};
    listen [::]:80 default_server{{#reuseport}} reuseport{{/reuseport}};
    listen 443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};
    listen [::]:443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};

    server_name _;

    {{> /usr/syno/share/nginx/X-Accel}}

我们使用另外的端口替换80,我使用的是 8080,使用 4430 替换 443。

server {
    listen 8080 default_server{{#reuseport}} reuseport{{/reuseport}};
    listen [::]:8080 default_server{{#reuseport}} reuseport{{/reuseport}};

    listen 4430 ssl{{#https.http2}} http2{{/https.http2}}{{#reuseport}} reuseport{{/reuseport}};
    listen [::]:4430 ssl{{#https.http2}} http2{{/https.http2}}{{#reuseport}} reuseport{{/reuseport}};

在上述的3个文件中都进行此种更改,配置完这一步,我们只是改变了用于生成 Nginx 配置文件的模板,而不是配置文件本身。所以我们现在还需要强制重建一下 Nginx 配置文件。应该是有一个终端命令来执行此操作,但还没有找到。我们可以在控制面板>>网络中更改任何设置并保存,这样会触发重建配置文件和重启动Web服务器。

或者使用命令(摘自网络大神,未经测试):

/usr/syno/etc/rc.sysv/nginx.sh reload
stop pkg-apache22
start pkg-apache22
reload pkg-apache22

至此,我们已经成功释放了 80 和 443 端口。

需要注意的是,修改完这里的 80 端口后,我们访问一些NAS服务就要使用上面修改后的 8080 (https: 4430)端口了(例如:Photo Station 等)。

3.转发 80/443 端口到 Docker 容器

我们可以在 Synology应用程序门户>>反向代理服务器规则中配置将所有通过 80 端口进入NAS的流量都转发到端口 8081 上,然后将 8081 端口再映射到 Docker 容器中的 80 端口(类似的,https 的 443 端口先转发到端口 4431上,再映射到 Docker 容器中的 443)。

你可能会觉得奇怪,从 80 端口到 8080 然后再回到 80,这不是多此一举吗。。其实原因很简单,群晖的Docker UI 中不允许我使用端口 80/443。

正确的修改如下:

反向代理服务器规则 配置如下(下图是我配置好之后的效果,后面介绍方法):

然而,前文已经提到,群晖千方百计的不让我们使用 80/443 端口,在直接配置 反向代理服务器规则 使用 80/443 端口时会有以下错误提示:

所以,这里我们要使用一点小小的手段,在 反向代理服务器规则UI 中我们可以先配置 12345 (https: 12346)端口,然后手动修改配置文件覆盖。

此处的配置文件是/usr/syno/etc/www/ReverseProxy.json

这个文件只是一个json文件,遗憾的是并没有格式化,因此不易阅读。这是我的(手动格式化了)配置文件,我们可以将其中的端口 12345 手动修改为 80 (https:12346 手动改成 443) 并保存文件。

{
	"592b270d-8fd2-4700-8fd0-e74969498929": {
		"backend": {
			"fqdn": "localhost",
			"port": 8081,
			"protocol": 0
		},
		"customize_headers": [],
		"description": "All",
		"frontend": {
			"acl": null,
			"fqdn": null,
			"https": null,
			"port": 12345,
			"protocol": 0
		},
		"proxy_connect_timeout": 60,
		"proxy_http_version": 1,
		"proxy_intercept_errors": false,
		"proxy_read_timeout": 60,
		"proxy_send_timeout": 60
	},
	"84b1e627-2820-4ad5-85a7-94fa59979037": {
		"backend": {
			"fqdn": "localhost",
			"port": 4431,
			"protocol": 1
		},
		"customize_headers": [],
		"description": "All_https",
		"frontend": {
			"acl": null,
			"fqdn": null,
			"https": {
				"hsts": false,
				"http2": false
			},
			"port": 12346,
			"protocol": 1
		},
		"proxy_connect_timeout": 60,
		"proxy_http_version": 1,
		"proxy_intercept_errors": false,
		"proxy_read_timeout": 60,
		"proxy_send_timeout": 60
	},
	"version": 2
}

如果你的反向代理规则比较多,该文件可能会比较大,小心修改即可。

下一次重新生成 Nginx 配置文件时(对Web设置进行任何更改),新端口号 80 将显示在规则中而不是 12345(https:443 将显示而不是 12346)。

至此,全部配置已经完成。

4.Docker 内 Nginx 设置反向代理

Docker>>容器>>Nginx>>详情>>终端机>>通过命令启动
使用命令bash

或者,在NAS ssh中使用

docker run -it nginx:latest /bin/bash

连接 nginx bash。

4.1 查找 Nginx 配置文件位置

使用nginx -t命令,返回:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok                
nginx: configuration file /etc/nginx/nginx.conf test is successful

/etc/nginx/nginx.conf即为配置文件路径。
可以使用 vim nginx.conf 编辑配置文件。
可能需要先安装vim,

apt-get update
apt-get install vim

国内源速度奇慢无比,试了几次都失败了。可以使用Docker的卷映射功能,映射NAS中的配置文件给docker nginx。
例如:

# 文件
docker/conf/nginx/nginx.conf --> /etc/nginx/nginx.conf
# 文件夹
docker/conf/nginx/conf.d --> /etc/nginx/conf.d
# 证书
document/cert/syno-acme/acme.sh/xxx.com --> /etc/nginx/cert

注意Docker容器的默认时区和主机不一致,还需要映射下时区文件

docker/etc/localtime --> /etc/localtime
docker/etc/TZ --> /etc/TZ
docker/etc/timezone --> /etc/timezone

需要先执行命令:cp /etc/localtime /volume1/docker/etc/

5.还有一件很重要的事

这只是为了安全意识。如果你定期运行安全顾问程序并让它检查已修改的文件,将看到关于我们修改的文件的警告信息。别担心,因为是我们修改的,所以这些文件并没有什么错。

你可以在应用程序属性中禁用此检查,但我强烈建议你不要。我的做法是:不禁用,忽略了这个警告。

温馨提示:修改系统文件属于危险操作,如果你没有足够把握,请不要随意修改。

6.附本机 Docker 内 nginx 配置(摘录如下)

# SSL 10 MB共享SSL会话缓存配置
ssl_session_tickets       off;
ssl_session_cache   shared:SSL:10m;
ssl_session_timeout 3600s;
# SSL cert, server {} can inherit this
ssl_certificate  /etc/nginx/cert/fullchain.cer;
ssl_certificate_key /etc/nginx/cert/xxx.com.key;
#TLSv1.3(需要openSSL支持TLS1.3)
ssl_protocols       TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:!aNULL:!eNULL:!LOW:!ADH:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
ssl_prefer_server_ciphers on;
# 开启HSTS
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload" always;

upstream photostation {  
	server 192.168.12.5:8080;
}
upstream photostation_https {  
	server 192.168.12.5:4430;
}

upstream dsm {  
	server 192.168.12.5:5000;
}
upstream dsm_https {  
	server 192.168.12.5:5001;
}

server {
    listen       80;
    server_name  "192.168.12.5" "xxx.com";

    location / {
	 	root   html;
		index  index.html index.htm;

		proxy_pass        http://dsm;
		client_max_body_size  3000m;
		access_log off;	
		proxy_set_header   X-Real-IP $remote_addr;
		proxy_set_header   Host      $http_host;
		
		#     : X-Frame-Options 防止点击劫持
		add_header X-Frame-Options SAMEORIGIN;
    }

    location /photo {
	 	root   html;
		index  index.html index.htm;

		proxy_pass        http://photostation;
		client_max_body_size  3000m;
  		access_log off;	
		proxy_set_header   X-Real-IP $remote_addr;
		proxy_set_header   Host      $http_host;
		
		add_header X-Frame-Options SAMEORIGIN;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

server {
    listen 443 ssl;
    server_name  "192.168.12.5" "xxx.com";

    ## send https request back to DSM
    location / {
	 	root   html;
		index  index.html index.htm;
		proxy_pass        https://dsm_https;
		client_max_body_size  3000m;

		#proxy_set_header Host $host;
		proxy_set_header   Host      $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;

		add_header X-Frame-Options SAMEORIGIN;

		access_log off;	
    }

    location /photo {
	 	root   html;
		index  index.html index.htm;
		proxy_pass        https://photostation_https;
    	client_max_body_size  3000m;

		proxy_set_header   Host      $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		
		add_header X-Frame-Options SAMEORIGIN;

		access_log off;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

https 可以参考:群晖 NAS Let's Encrypt 泛域名证书自动更新

7.域名访问群晖导致虚拟机novnc不正常的解决方法

解决方法来自dsm-reverse-proxy-websocket

首先自行备份/usr/syno/share/nginx/Portal.mustache文件,然后编辑该文件并在location字段内添加如下内容:

proxy_set_header   Upgrade           $http_upgrade;
proxy_set_header   Connection        "upgrade";
#proxy_http_version 1.1;
proxy_read_timeout 86400;

然后重启网络。

sudo synoservicecfg --restart nginx

(目前测试无效,用ip可以访问,等待后续再看吧。。)

这个问题理论上和Docker下查看终端机失败是一个问题。

7.1 DSM 6.2.1 及以上

从 DSM 6.2.1 开始,不再需要修改 Portal.mustache 文件,如果按照上面的方法,反而可能导致错误 。

操作步骤:

控制面板 --> 应用程序门户 --> 反向代理服务器
修改 https 的 启用 HTTP/2 + 增加自定义标题 新增下拉 WebSocket。

或者还可以使用三方Docker图形化管理工具Portainer的Exec Console功能。

参考

Freeing up port 80 on Synology DSM | Tony Lawrence
【NAS-群辉玩机之旅-nginx】使用反向代理实现多域名访问不同应用,规避IP+端口访问

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区