局域网(LAN)中子域名映射至不同设备的实现方案及相关疑问
首先先解答你最关心的那个疑问:是的,路由器收到的请求里确实包含客户端访问的域名。
如果是普通HTTP请求,请求头里的Host字段会明确标注客户端要访问的域名(比如computer1.mynetwork.info);如果是HTTPS请求,在TLS握手的初始阶段,客户端会通过SNI(Server Name Indication)扩展告诉服务器要访问的域名——只要你的路由器或者后续的转发设备能读取到这个信息,就能实现基于域名的转发。
接下来回到核心需求,除了你已经知道的端口转发,还有两种更优雅的实现方式:
1. 利用路由器的虚拟主机(Virtual Host)转发功能
不少高端家用路由器,或者刷了第三方固件(比如OpenWrt、DD-WRT、梅林固件)的路由器,都支持基于域名的转发规则,也就是常说的“虚拟主机转发”。具体操作大概是这样:
- 登录路由器管理后台,找到“端口转发”“虚拟主机”或者“域名转发”相关的配置页面;
- 添加两条规则:
- 第一条:匹配Host为
computer1.mynetwork.info,转发到内网中computer1的IP(比如192.168.1.100)的对应端口(比如80/443); - 第二条:匹配Host为
computer2.mynetwork.info,转发到computer2的内网IP(比如192.168.1.101)的对应端口;
- 第一条:匹配Host为
- 保存规则后,外部请求只要访问对应的子域名,路由器就会自动把流量转到内网对应的机器上,不用给每个机器分配不同的公网端口。
2. 内网部署反向代理服务器
如果你的路由器不支持虚拟主机转发,或者你需要更灵活的配置(比如处理HTTPS证书、添加缓存、负载均衡),可以在内网里找一台机器(或者用一个低功耗的设备比如树莓派)部署反向代理服务,常用的工具是Nginx、Traefik或者Caddy。
举个Nginx的简单配置例子:
# 处理computer1的请求 server { listen 80; server_name computer1.mynetwork.info; location / { proxy_pass http://192.168.1.100; # 指向computer1的内网IP和端口 proxy_set_header Host $host; # 把原请求的Host头传给内网机器 proxy_set_header X-Real-IP $remote_addr; } } # 处理computer2的请求 server { listen 80; server_name computer2.mynetwork.info; location / { proxy_pass http://192.168.1.101; # 指向computer2的内网IP和端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
配置好之后,只要在路由器上把公网的80端口(如果用HTTPS就是443端口)转发到这台代理服务器的内网IP,外部的请求就会先到代理服务器,再由它根据域名转发到对应的内网机器。
这种方法的优势在于扩展性很强,后续如果要加更多子域名,只需要在代理服务器上添加对应的配置即可,还能统一管理HTTPS证书(比如用Let's Encrypt申请泛域名证书)。
最后补充一点:不管用哪种方法,都要确保内网对应的机器防火墙允许外部(通过路由器/代理)访问对应的端口,同时你的ISP没有封禁80/443这类常用端口(如果被封禁,可以改用其他端口,比如8080/8443,然后访问的时候加上端口号,或者在代理服务器上做端口映射)。
备注:内容来源于stack exchange,提问作者Iftikhar Ali




