本帖最后由 姚远 于 2020-3-21 13:18 编辑
首先鸣谢网上各路大神,我这里都是从大神那里搬过来的,并把我迈过的坑填好,给初学小白一个参照。跟着我来,小白的你一定有所收获。 为什么要使用Nginx代理在家庭智能化应用过程中,我们难免需要与外网进行信息交互。如果仅仅是访问外网,我们现在光猫+路由器+wifi的机制完全可以胜任。但如果需要外网访问内网的时候,比如智能音箱需要读到我们内网的hass主机,企业微信推送hass消息也需要腾讯读到我们的内网消息。此时这个机制就不足了。当外网需要https安全访问内网时,我理解需要至少走两步,第一步穿透到内网中来,打通网络通道。第二步进行ssl验证,否则https是不能访问的。
那Nginx可以做什么?它本质上就是一个外网到内网的”桥“,通过这个桥,你就可以安全的内网互通,尤其是可以通过自定义端口,将一个域名、自定义不同端口,访问到内网不同的服务器、不同的应用。
所以,nginx很强大。但要特别注意一点,你的外网必须可以穿透进来。否则一切都是废话,白忙活。 外网穿透进来的必要条件:你的进户ip必须可以在外网访问得到。百度搜索输入”ip“,看看是你家光猫进口的ip吗?如果不是,找运营商开通。”喂,我家有智能设备应用,需要给我开通公网ip“,就这么简单。
另外一个问题,我的hass应用可以配置https,我还需要这个”桥“吗?说说我的惨痛教训。 我之前由于种种原因,外网穿透进来之后,在hass中直接配置了https认证,一切应用还不错。但接下来出现麻烦了。在启用hass配置https外网访问后,hass运行全程需要ssl认证,这就导致node-red,esphome等与hass集成的内网应用出现各种状况。尤其是esphome是为hass配套的固件系统,没有找到其与ssl相关的处理方式,彻底不能用了。不得已必须取消hass的ssl认证的运行方式。此时花生棒等ddns服务也是一个很好的选择。但花生棒绑定的https服务,只能一个棒对应一个https应用,而hass和微信的集成应用时,企业微信如果要安全接入进来,就会遇到外网端口不够的情况。
至此,就需要一个决策,hass要非ssl运行方式,家里对外网端口又需要可以承担多个应用的穿透。Nginx可能是一个比较好的选择。尤其是nginx网上教程较多,虽然配置有些麻烦,但反向代理,可以为今后多个内网穿透提供统一的服务。我选择nginx做什么?就是建立一个代理服务器,一个桥,将内外网进行安全转发。内网应用不做变化,外网应用可安全映射到内网应用上。 安装nginx想明白了,就开始安装吧。我是树莓派3,没有docker,直接安装。 1 安装网上安装教程很多,官网教程更较详细。我是参考:树莓派安装Nginx,
sudo apt-get install nginx
2 启动
sudo /etc/init.d/nginx start
3 测试安装是否成功nginx默认端口:80 看到如下页面,nginx就安装成功了 4 简单试运行1 目的:体会和理解nginx的运行机制。
sudo nano /etc/nginx/sites-available/default
2 修改其中一段代码,其他不要动,不要动,不要动 找到server下面的listen行:修改两处的监听端口。就是试试原先80端口,现在改为8888端口,体会nginx是做什么的
3 保存配置,重新启动nginx服务
sudo /etc/init.d/nginx reload
4 浏览器上访问,你的ip:8888 如果能看到刚才的欢迎页面,就是说明端口转发了。如果没看到,那回过头看看配置中的端口是8888吗?是哪个端口号,你浏览器就输入哪个端口号。
5 设置开机自启动服务1 设置开机启动
systemctl enable nginx.service
2 启动nginx服务
systemctl start nginx.service
3 设置开机自启动
systemctl enable nginx.service
4 其他服务命令
需要的时候再有针对性的执行这些命令
systemctl disable nginx.service # 停止开机自启动
systemctl status nginx.service
systemctl restart nginx.service
systemctl list-units --type=service
简单配置试验
建议小白一定要做,一定要做,一定要做。 为什么小白要做?因为坑来了,很大很大,但又是很简单很简单。还有一个要做的原因,深入理解nginx能做啥,怎么做的。这不需要我们成为专家,但至少要知道出问题会是哪里,抄大神配置的时候怎么抄,自己搞点小配置怎么配。我是磕磕碰碰,在这里绕了几个月都没有出来。人太笨了。
外网访问路由器路由器是外网入户的第一关,进门就是路由器,所以你必须要能访问到了。之后,你用https访问,ssl验证就需要nginx了。所以,这里的外网访问是说https访问。
目标:理解ssl的配制方法,以及通过外网https访问路由器。
要真正配置nginx了,第一个坑来了,最大最大的坑。就是网上看的所有教程,都是配置的片段,而不是全部。如果你把这个片段拷贝成你的配置文件,你就和我一样,死定了。 我理解nginx分为四大部分,初始块、events、http、server。初始块、events、http三大块,就先认为是全局的、固定的,以后碰到具体问题再去看他们。我们需要配置的,也是网上各种教程配置的,基本都是server块。所以,一定一定先盯住server{},其他三大块暂时不动。这就是坑!
修改配置文件,是/etc/nginx/sites-available/default还是/etc/nginx/nginx.conf。应该是/etc/nginx/sites-available/default文件。但是我之前犯了一个错误,将/etc/nginx/nginx.conf全面替换为只有server{}的内容,导致无法启用/etc/nginx/sites-available/default配置文件。虽然后面重新进行了补充和修改,但没有再启用/etc/nginx/sites-available/default,而是将所有的配置都放到了/etc/nginx/nginx.conf文件中。所以我后面的配置都是在/etc/nginx/nginx.conf做的。各位如果安装之后立即配置,应该在/etc/nginx/sites-available/default中。nginx基础配置文件中有句话,将详细配置指向了/etc/nginx/sites-available/default文件。但我由于初始时破坏了源文件,也找不到这句话的位置了。所以,都在/etc/nginx/nginx.conf文件里进行的配置,以后有机会再改吧。 保持其他三大块不动,配置外网https访问路由器。 注释掉原先的server{}的内容,替换为:
server {
server_name 你已经ssl认证过的域名;
listen 你在路由器端口转发到内网的端口号 ssl;
ssl_certificate /etc/nginx/cert/你的ssl证书的pem文件名;
ssl_certificate_key /etc/nginx/cert/你的ssl证书的key文件名;
ssl_prefer_server_ciphers on;
location / {
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host:$server_port;
proxy_pass http://你的路由器ip;
}
注意几点
1. 运营商封了你的端口号?你一个域名想访问多个应用?没关系你在外网访问的时候加上端口号就行了。经过路由器映射进来,在nginx还可以映射一次,转向你的应用。 我的整体访问配置就是:
2. ssl,加上这个就是https访问。如果直接写”listen 9001“,是http访问,就不需要ssl了。
3. ssl证书尽量放在nginx之下,否则读写这个文件的权限问题就能搞死小白
4. location下的内容,暂时理解为就是你内网代理的一堆设置。那个http已经是内网的了,所以按照内网配置就可以了。
我的是在/etc/nginx/nginx.conf文件配置的,完整的nginx.conf文件内容如下:
#user root;
worker_processes 1;
#error_log logs/error.log; error_log logs/error.log notice; error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent"
# "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
server_name 你的ssl认证并可解析的域名;
listen 9001 ssl;
ssl_certificate /etc/nginx/cert/cert_nginx.pem;
ssl_certificate_key /etc/nginx/cert/cert_nginx.key;
ssl_prefer_server_ciphers on;
location / {
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host:$server_port;
proxy_pass http://192.168.3.1;
}
}
}
插播ssl证书的下载和安装在配置路由器https访问之前,我们应该已经下载并安装好了ssl证书。这里插播这个章节,主要是很多像我一样的小白会在这里迷茫,会犯错误。所以在这里特别提出来进行补充。 请先确保你已经申请ssl证书,验证通过,并绑定域名,可以进行正常解析,解析是正确的,可以通过http访问进你的内网。可以访问进内网,说明你外网穿透成功了,才可以进行后续的nginx。注意,此时的访问是没有配置nginx之前的访问,我这里的章节是插播的。
1. 下载ssl证书 下载证书,nginx版:下载域名所对应的ssl证书;下载nginx版
2. 解压并放置到nginx服务器
3. 检查ssl证书的文件名、放置目录,是否与nginx配置文件相符
重启nginx访问路由器
sudo nginx -s reload
外网访问hass
配置文件/etc/nginx/nginx.conf
注意,你的配置文件应该是/etc/nginx/sites-available/default 这个配置相对比较复杂,要特别注意几点:
1. 有一部分内容放到了server之外,http块下,这个要注意
2. server{}中listen监听的端口,是你路由器映射之后的端口,别搞错了。
我的路由器映射端口
我的nginx配置端口
3. server{}中listen监听,我只启用了ssl,也就是只有https服务才过nginx。我不打算外网http访问。
4. server{}中location的ip和端口,是你内网访问的端口,内外有别,这里配置内网的。
完整的配置文件
直接上完整的配置文件,免得小白走我的坑。注意,我是在/etc/nginx/nginx.conf下的配置。你在下的配置文件/etc/nginx/sites-available/default可能只需要其中的server{}部分。由于我前面犯的错误,找不到原始的/etc/nginx/nginx.conf文件了,不知道里面的配置是哪一段指向了你的配置文件。请千万千万注意。
#user root;
worker_processes 1;
#error_log logs/error.log; error_log logs/error.log notice; error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent"
# "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
#gzip on;
server {
server_name 你的ssl认证并可解析的域名;
listen 9001 ssl;
ssl_certificate /etc/nginx/cert/cert_nginx.pem;
ssl_certificate_key /etc/nginx/cert/cert_nginx.key;
ssl_prefer_server_ciphers on;
location / {
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host:$server_port;
proxy_pass http://192.168.3.1;
}
}
server {
listen 3352 ssl http2;
ssl_certificate /etc/nginx/cert/cert_nginx.pem;
ssl_certificate_key /etc/nginx/cert/cert_nginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_timeout 10m;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_buffer_size 1400;
add_header Strict-Transport-Security max-age=15768000;
ssl_stapling on;
ssl_stapling_verify on;
server_name 你的ssl认证并可解析的域名;
access_log /var/log/nginx/你的ssl认证并可解析的域名_nginx.log combined;
error_log /var/log/nginx/你的ssl认证并可解析的域名_nginx.error.log debug;
index index.html index.htm index.php;
if ($ssl_protocol = "") {
return 301 https://$host$request_uri;
}
#error_page 404 /404.html;
#error_page 502 /502.html;
charset utf-8; #默认编码方式
client_max_body_size 75M;
# 其他的请求全部交给Python的uWSGI来处理
location / {
proxy_pass http://127.0.0.1:8123;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
如果你的配置文件三大公共块和我配置不一样,不用管他,盯住server{}部分就行了。
重启nginx访问路由器
sudo nginx -s reload
配置hass,使得小度音箱可用
完全内网配置,不需要配置http,不需要ssl配置,内网ip访问配置
注意:
至此,小白nginx基本应用就告一段落了。后面我在集成企业微信、简单图片服务器都使用到了nginx,而且配置都很简单。就是网上的教程太坑人了。小白们一起交流吧
|