AppServer/

集中 ssl 反向代理服务器的建设

发布
更新
字数
1007
阅读
3 分钟

一直想弄这个东东。
面临的现状是:
1、公网 ip 相当有限;
2、需要对外提供的 80/443 端口服务的内网服务器很多;
3、想要使用免费的易于部署的 ssl 证书。

实现手段是:
1、使用反向代理实现单公网 ip 单端口映射内网多台服务器;
2、使用 let’s encrypt 证书进行一处部署和更新,内网外网通用。

具体操作如下:
架设好内网反向代理服务器。在这儿用的是 nginx@freebsd 。
在这儿有个问题。如果使用了 ssl 证书的话,同时做了反向代理,那么就要在内网服务器和反向代理服务器上同样加载证书才可以。而且,如果使用 let’s encrypt 证书的话,由于它有一定周期性,还要保证在一定的周期内可以两边都自动同步。这是个麻烦事。有没有集中部署统一更新的方法呢?有。
首先,将需要进行反向代理的服务器对应的域名,都解析到反向代理服务器上。业务服务器上无论是 iis 的主机头还是 apache 的 vhost 都没关系。只要它们设置好了 server_name 就可以了。然后很重要的一点就是在反向代理服务器上设置 hosts ,将业务服务器 ip 和业务服务器需要对外的域名对应起来。
这样做的目的就是要无论内外网中,大家访问业务服务器的时候是经由反向代理服务器的,而在反向代理服务器本地,由于需要进行反向代理,所以需要通过域名来找到业务服务器,所以需要在本地添加 hosts 来覆盖掉内网 dns 服务器做的业务服务器解析。
OK,解决了这个先决的问题之后,可以开始进行反向代理和证书的设置了。
在主配置文件 nginx.conf 中,我们按域名分开不同的配置项,如:

bash
include conf/rp_test.test.com.conf;

然后再看看 rp_test.test.com.conf 里面的配置:

bash
server {
    listen       192.168.1.10:80;
    listen       192.168.1.10:443 ssl http2;
    server_name  www.mydomain.com;

    location /.well-known/ {
        default_type "text/plain";
        alias /usr/local/www/nginx/.well-known/;
    }

    if ($scheme = 'http') {
        return 301 https://www.mydomain.com$request_uri;
    }

    ssl_certificate /usr/local/etc/letsencrypt/live/www.mydomain.com/fullchain.pem;
    ssl_certificate_key /usr/local/etc/letsencrypt/live/www.mydomain.com/privkey.pem;
    ssl_stapling on;
    ssl_stapling_verify on;

    if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})"){
        set $year $1;
        set $month $2;
        set $day $3;
    }
    access_log  /var/log/nginx/www.mydomain.com/ssl.access.$year$month$day.log main;
    error_log  /var/log/nginx/www.mydomain.com/ssl.error.log;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header Accept-Encoding "";
        proxy_set_header X-Forwarded-Ssl on;
        proxy_pass_header  User-Agent;

        proxy_pass     http://www.mydomain.com;
        proxy_redirect http:// $scheme://;

        sub_filter_types text/css text/xml;
        sub_filter http://$host $scheme://$host;
        sub_filter_once off;
    }

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

然后重启就可以了。
需要注意的是,如果内网有 wordpress 服务器的话,可能仍然有一些 js 之类的走 http 不能被 https 正常加载,怎么办?有一个 SSL Insecure Content Fixer 或 really-simple-ssl 的插件可以解决这个问题。

如此,就大功告成了~

Edit:
血的教训啊…
在使用命令行申请证书的时候:

bash
certbot certonly --email root@mydomain.com --webroot -w /usr/local/www/nginx -d www.mydomain.com

里面的 -w 对应的值要千万和配置项中的 location /.well-known 中对应的一致。否则会显示如下的错误:

bash
Failed authorization procedure. www.mydomain.com (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://www.mydomain.com/.well-known/acme-challenge/hPixJOxDwVHzxw-W625Yc6H9-oWN6yPccWkrwM_KJDJc [8.8.8.8]: 404

IMPORTANT NOTES:
- The following errors were reported by the server:

Domain: www.mydomain.com
Type:   unauthorized
Detail: Invalid response from
http://www.mydomain.com/.well-known/acme-challenge/hPixJOxDwVHzxw-W625Yc6H9-oWN6yPccWkrwM_KJDJc
[8.8.8.8]: 404

To fix these errors, please make sure that your domain name was
entered correctly and the DNS A record(s) for that domain
contain(s) the right IP address.

Edit(20200409):
当初想得太复杂,其实很简单,在反代上统一更新证书,然后域名都解析到反代,反代上配置代理内网 ip 就好了。

评论

正在载入评论…

留下评论

人机验证
四位数字,看不清可点击图片刷新

评论经审核后显示。

回到顶部 ↑