折腾OpenWRT那些事——nginx反向代理

起源

我只是想让DDNS访问和内网访问时都能使用正确的证书,但是uhttpd似乎不支持对模糊的接口指定专用的证书。因此我就想到了反向代理之神 nginx 。对于方式,不能使用直接的网站服务模式,因为其中包含很多 uci 控制命令,nginx 无法识别。因此工作方式为 uhttpd 运行处理 uci ,nginx 接受外部流量并进行转发。

思路

准备让uhttpd监听在一个偏僻的端口,同时为了防止好事者乱访问,仅允许本地访问,让nginx的流量转发即可。

开整

也不多说别的了,这个肯定得做:

opkg update
opkg install nginx

我们先让 uhttpd 监听在一个仅可本地访问的不常用端口上,而且关掉它本身的 HTTPS 跳转。可以按照如下指示编辑 uhttpd 文件。

  • /etc/config/uhttpd 内容
        config uhttpd 'main'
        list listen_http '127.0.0.1:11480'  # 这是uhttpd监听的端口,最好保持本地访问
        option redirect_https '0'  # 废物uhttpd不配处理SSL,让nginx代劳
        option home '/www'
        option rfc1918_filter '1'
        option max_requests '50'
        option max_connections '100'
        option cert '/etc/uhttpd.crt'
        option key '/etc/uhttpd.key'
        option cgi_prefix '/cgi-bin'
        list lua_prefix '/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua'
        option script_timeout '3600'
        option network_timeout '30'
        option http_keepalive '20'
        option tcp_keepalive '1'
        option ubus_prefix '/ubus'
        list ucode_prefix '/cgi-bin/luci=/usr/share/ucode/luci/uhttpd.uc'

config cert 'defaults'
        option days '730'
        option key_type 'ec'
        option bits '2048'
        option ec_curve 'P-256'
        option country 'ZZ'
        option state 'Somewhere'
        option location 'Unknown'
        option commonname 'OpenWrt'

好的,接下来就可以配置 nginx 了,这是nginx.conf。可以参考如下内容:

  • /etc/nginx/nginx.conf

user  nobody nogroup;  #  这里注意一下,OP中不是nobody:nobody形式,而是nobody:nogroup形式,使用特定不可登录用户更安全。
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 80;
        server_name your.domain 192.168.114.1;  #  这里设置你的其它登录别名
        return 301 https://your.domain$request_uri;  #  这里带URI转发,防止别人第一次必回首页而红温
    }

    server {
        listen 443 ssl http2;
        server_name op.ncc.local;

        ssl_certificate /etc/nginx/ssl/path;
        ssl_certificate_key /etc/nginx/ssl/path;

        location / {
            proxy_pass http://127.0.0.1:11480;  # 这里放uhttp的配置监听端口
            proxy_set_header Host $host;
            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;

        }
    }
}

我则是配置了 SNI 来实现不同域名给不同证书:


user  nobody nogroup;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 80;
        server_name op.ncc.local 192.168.114.1;
        return 301 https://op.ncc.local$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name op.ncc.local;

        ssl_certificate /etc/nginx/ssl-crts/op.ncc.local/op.crt;
        ssl_certificate_key /etc/nginx/ssl-crts/op.ncc.local/op.key;

        location / {
            proxy_pass http://127.0.0.1:11480;
            proxy_set_header Host $host;
            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;

        }
    }

    server {
        listen 80;
        server_name nancunchild.zapto.org;
        return 301 https://nancunchild.zapto.org$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name nancunchild.zapto.org;

        ssl_certificate /etc/nginx/ssl-crts/nancunchild.zapto.org/op.crt;
        ssl_certificate_key /etc/nginx/ssl-crts/nancunchild.zapto.org/op.key;

        location / {
            proxy_pass http://127.0.0.1:11480;
            proxy_set_header Host $host;
            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;
        }
    }
}

题外话

感觉这个真的不难,也就是nginx不会用,看来这个东西确实有一点学习曲线。对了,关于校内DDNS 需要带SSL证书,好像不好找到免费的,毕竟那个bot只给公网IP玩。所以我找到的是no-ip的动态域名提供商,每年得给他几美刀充值最便宜的套餐来换动态域名SSL证书。
而且注意,不知道什么原因,直接在OP里面下载的DDNS插件似乎没有针对no-ip的脚本,但是你可以在opkg里找到可以单独安装的no-ip脚本,安装后就多出no-ip的选择项。

参考

nginx多https证书配置精简(CSDN)
no-ip官网(别导航到俄罗斯的那个noip了)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注