使用nginx和路由器进行内网免端口进行应用访问

作者:西北望天狼

我家里一个软路由,一个unraid 和一个威联通,家里的设备倒是没增加了,但是网络应用在不断增加。

每增加一个应用肯定需要一个端口,有些还必须要有一个IP。

ip 加端口本身是很难进行记忆,对一些访问频次比较高的应用还好,能够记得住,但是对于一些不常用的应用,访问的时候就需要先打开控制台,我这里是unraid ,找到安装的位置,在找配置,然后在拼一个访问地址进行访问。整个过程很繁琐,会直接导致应用的使用效率打折扣。

下图是我unraid 中的应用

还有在不同机器的威联通,黑群,两个软路由以及一些开发服务,如git、rabbitmq等应用。

以我目前的知识范围,有两种方式可以解决这个问题,一个是搭建导航页,一个是自定义访问域名。

作为一个成年人,并且为了提高文章的质量,我选择都要。

自定义域名

首先是自定义一个域名

这个域名可以是域名服务商托管的,也可以自己定的。域名服务商托管的好处就是可以在外网访问时也可以直接通过域名进行访问。当然,对于自定义的内容就只能自己家里网络访问。

这里我们假设你的一级域名为 abc.com

首先我们有一个路由器,可以是软路由也可以是硬路由,但都必须要有一个自定义host 的功能,或者说能够进行dns 拦截的能力。

我使用的是爱快,设置起来要稍微复杂一些,在dns 设置中按照图中的设置即可,当然,首选DNS和备选DNS按照自己的喜好填就是,剩下的就是必须开启DSN代理,然后自己电脑的DNS 需要指定为网关的地址,我这里是爱快的地址。

对于其他的路由器,往往都有自定义host 或者自定义挟持域名的功能。

需要注意的是,如果有旁路由,需要同时在主路由以及旁路由进行自定义域名的配置。

接下来我们进行第一个域名访问的配置,这里我们以jellyfin 的配置举例

首先在自定义域名的位置新增一项,域名填写video.abc.com,备注为jellyfin 。最重要的是ip ,ip 地址需要填写一个具有nginx的服务器地址,具体的用途下文讲解。

需要注意的是,对于端口固定为80的应用,如unraid控制台,爱快控制台等,此处的ip 可以直接填写为所在的ip ,可以直接实现自定义域名访问。

我这里是把所有的的域名全部执行了同一个ip 地址,为以后做自定义dns 做准备。

安装nginx服务

首先创建一个linux的虚拟机,我这里使用的unraid ,安装的ubuntu20,具体的安装方式不展开介绍,安装配置如图所示:

其他使用默认即可。

安装完成之后,我们登录到虚拟机,创建nginx 的配置文件

第一步:创建配置文件夹,执行以下命令

mkdir -p ~/docker/nginx/conf.d

第二步:创建配置文件nginx.conf,执行以下命令

注意,以下命令为单条命了,全部复制后,一次执行。

tee ~/docker/nginx/nginx.conf

error_log  /var/log/nginx/error.log warn;

pid        /var/run/nginx.pid;

worker_rlimit_nofile 65535;

events {

   worker_connections  10240;

}

http {

   include       /etc/nginx/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  /var/log/nginx/access.log  main;

   sendfile        on;    #tcp_nopush     on;

   keepalive_timeout  300s;

   client_header_buffer_size 8192k;

   large_client_header_buffers 4 8192k;

   gzip  on;

   client_max_body_size  5000m;

   map $http_upgrade $connection_upgrade {

       default upgrade;         close;

   }

   include /etc/nginx/conf.d/*.conf;

}

stream {

  include /etc/nginx/conf.d/*.stream;

}

EOF

第三步:创建配置文件vidoe.abc.com的域名映射文件 video.conf,执行以下命令

后面每新增一个自定义域名,我们就需要新增一个对应的xxx.conf 文件,并分别替换

命令中的server_name 后面的内容以及 proxy_pass的内容。

tee ~/docker/nginx/conf.d/video.conf <    listen       80;

   server_name  video.abc.com;

   client_max_body_size 50M;    #charset koi8-r;

   #access_log  /var/log/nginx/host.access.log  main;

   location / {        # 此处跟换为自己的jellyfin 的访问ip 加端口

       proxy_pass   http://[更换为自己的jellyfin的ip和端口];

       proxy_connect_timeout 10s;

       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_http_version 1.1;

       proxy_set_header Upgrade $http_upgrade;

       proxy_set_header Connection "upgrade";

   }

}

EOF

最后,创建nginx 的docker 容器

 docker run --name nginx -v ~/docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro  -v ~/docker/nginx/conf.d:/etc/nginx/conf.d -p 80:80  -d nginx:1.20-alpine --restart=always

新增域名以及配置文件后,需要重启nginx 服务,重启命令为:

docker restart nginx

自定义导航页

自定义导航我使用的是最近站内很火的heimdall ,这里我把导航页安装在了和nginx同一台虚拟机中,也是通过docker 的进行安装

第一步创建配置文件夹

mkdir -p ~/docker/heimdall/config

第二步创建heimdall 容器

docker run -d

 --name=heimdall

 -e PUID=1000

 -e PGID=1000

 -e TZ=Europe/London

 -p 8000:80

 -v /home/zrc/docker/heimdall/config:/config

 --restart unless-stopped

 lscr.io/linuxserver/heimdall:latest

第三步,把导航页作为 abc.com 的根域名进行访问

    首先,把abc.com 在路由器中进行指定,具体参考上文

    然后,把abc.com 作为nginx 的默认配置,也就是说在 ~/docker/nginx/conf.d 中增加一个default.conf ,并指定域名

    具体的命令为:

    同样的,以下命令为单行,需要复制后一次执行。

tee ~/docker/nginx/conf.d/default.conf <    listen       80;

   server_name  abc.com;

   client_max_body_size 50M;    #charset koi8-r;

   #access_log  /var/log/nginx/host.access.log  main;

   location / {

       proxy_pass   http://172.17.0.1:8000;

       proxy_connect_timeout 10s;

       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_http_version 1.1;

       proxy_set_header Upgrade $http_upgrade;

       proxy_set_header Connection "upgrade";

   }

}

EOF

需要注意的是,我把nginx 和heimdall 都是采用了docker并安装到了同一个虚拟机,所以我这里的proxy_pass 的ip 为docker0 的ip ,也就是docker 默认的网桥地址。

最后一步,重启nginx 即可。

docker restart nginx

剩下的域名按照文中的步骤进行添加即可,路由器中添加一个域名,新增一个nginx 的配置文件,重启nginx ,导航页中添加即可。

FAQ

为什么不直接使用docker 创建nginx

我测试过用unraid 直接创建一个nginx ,使用新的ip ,但是我发现创建出的容器无法访问局域网内的设备,是直接无法连接,可能可以通过路由表的方式进行映射,我觉得也挺麻烦,就直接新增了一个虚拟机,并把闲置调整到最低

为什么把导航页和nginx 放到同一个虚拟机中

这里有两个目的,第一个是nginx 和导航页作为同一类应用,按照职责来说他们是一样的,所以放到了一起

另外一个为了进行演示,docker 之间互相访问,需要使用的ip

为什么不使用unraid 自带的nginx 进行配置

unraid 自带的nginx我验证过,首先是重启后会还原,当然可以用挂载的方式,然后是我也验证过,不知道是版本的问题还是别的原因,配置始终不成功。