V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要把任何和邀请码有关的内容发到 NAS 节点。

邀请码相关的内容请使用 /go/in 节点。

如果没有发送到 /go/in,那么会被移动到 /go/pointless 同时账号会被降权。如果持续触发这样的移动,会导致账号被禁用。
dLvsYgJ8fiP8TGYU
V2EX  ›  NAS

如何将 LAN 中设备发往公网指定 domain:port 的 HTTPS 请求重定向到 LAN 中指定设备的 ip:port

  •  
  •   dLvsYgJ8fiP8TGYU · 2021-02-26 02:30:00 +08:00 · 4255 次点击
    这是一个创建于 1367 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景: 家中运行一台 NAS,为实现从公网(使用移动数据)访问,已通过一台拥有公网 IP 地址的云服务器配置端口转发服务,并申请了域名及 SSL 证书,目前运行良好。

    用 PPT 画了个网络拓扑: https://i.imgur.com/0yGEJ6C.png

    在外面使用移动数据连接家里的 NAS,需要访问云服务器的指定端口(示例: https://nas.example.com:12345 ),在这一过程中需要消耗云服务器的流量(废话)。

    如果我回到家里,在局域网中访问上述 domain:port,依然可以成功连接 NAS,但还是需要消耗云服务器的流量。这部分流量其实消耗的有点冤,毕竟已经在同一个 LAN 里面了,按理说可以直连的。这样子不但多交钱,延时也增加了。

    问题: 是否可以通过某种方式在局域网中重定向发往 nas.example.com:12345 的请求,使其无需经由云服务器中转而直接发往局域网中的 NAS 的指定端口?

    1. 尽可能避免用户在设备端进行操作,如记住不同的 ip:port,在网络环境变化时手动输入(可行,但用户操作不便,排除)

      • 我个人其实无所谓,主要是考虑到家里其他人不太懂计算机 /网络这块,
    2. 已经尝试过以下方案,效果均不好

      • 修改 hosts
        • 在 iOS 设备基本不可行,且离开局域网即失效
      • 在 NAS 上搭建基于 AdGuard 的 DNS 服务器
        • 在网络环境变换时,比如出门 /刚回家,可能是由于 DNS 缓存,不能实现无缝无感切换
        • 改 DNS TTL 有用吗?
    3. 可能可行的其他方案?

      • 路由器设置策略路由或其他某种设置
        • 对现有硬件改动最小。TP-LINK 企业级路由器,不清楚是否支持这样操作
      • 新增一个软路由?
      • 在 iOS 上运行某种支持通过判断当前 SSID 并修改请求的软件?
    4. NAS 用的是群晖,5001 是 HTTPS 端口

    5. 如果能实现 IP 地址重定向,但无法同时实现端口重定向,可妥协

      • 在 NAS 也开启 12345 端口,与云服务器端口号实现同步,并允许相应服务使用此端口
      • 云服务器端口需保持至少 10000+ 高位,以保证安全
    43 条回复    2021-03-01 09:36:32 +08:00
    learningman
        1
    learningman  
       2021-02-26 02:46:40 +08:00 via Android
    可以,iptables SNAT 和 DNAT,DNS 管不了端口的
    f165af34d4830eeb
        2
    f165af34d4830eeb  
       2021-02-26 02:52:44 +08:00 via iPhone
    常见的手段就是内网 dns 劫持和 ip 重定向。感觉这篇文章应该可以帮到你。

    https://www.zhoujiangang.com/p/iptables-redirect-ip/
    f165af34d4830eeb
        3
    f165af34d4830eeb  
       2021-02-26 03:09:41 +08:00 via iPhone
    额外说一句,保证安全可不是靠高位端口这种野路子,外网访问内网走 vpn 更稳妥,不建议把私人 web 服务暴露在公网上。
    Niphor
        4
    Niphor  
       2021-02-26 04:00:50 +08:00
    你路由器 host 里加一条,像 op 的话直接加 dnsmasq 里
    ysc3839
        5
    ysc3839  
       2021-02-26 04:13:14 +08:00 via Android
    nas.example.com 解析到云服务器,然后在路由器上修改 hosts 让 nas.example.com 指向 NAS 不就好了吗?为什么离开局域网失效不可行?你离开了局域网不是要走云服务器吗?
    Sylv
        6
    Sylv  
       2021-02-26 06:29:34 +08:00 via iPhone
    首先路由器得支持 dnsmasq (我是华硕路由器刷了梅林系统)。

    然后 ssh 到路由器上。

    编辑 dnsmasq 配置文件:
    vi /jffs/configs/dnsmasq.conf.add

    加入将 NAS 域名解析到内网 IP 的规则,例如:
    # NAS
    address=/mynas.com/192.168.1.10

    然后重启 dnsmasq:
    service restart_dnsmasq

    这样一来,内网访问 mynas.com 时就会通过路由器 dnsmasq 解析为内网 IP 192.168.1.10 ,直接内网访问 NAS,不需要出去外网再绕回来;外网访问时还是解析为外网 IP 。
    soulzz
        7
    soulzz  
       2021-02-26 08:54:56 +08:00
    @Sylv 楼主说的是 dns 缓存的问题,切换网络时会造成体验中断,你这种和用 adguardhome 没区别

    建议楼主向 isp 要一下动态公网 ip 做一下 ddns,不行的话考虑换个运营商
    weyou
        8
    weyou  
       2021-02-26 09:19:49 +08:00 via Android
    在路由器上将所有的 DNS 请求强制重定向到自己的 DNS 服务器可以解决缓存的问题。
    比如在 Openwrt 路由上可以设置 Firewall Custom Rule:
    iptables -t nat -I PREROUTING 1 -i br-lan -p udp --dport 53 -j DNAT --to-destination <自己的 dns ip 地址>:53
    weyou
        9
    weyou  
       2021-02-26 09:23:38 +08:00 via Android
    会错意了,上述并不能解决已解析好的域名地址缓存
    tankren
        10
    tankren  
       2021-02-26 09:26:37 +08:00
    在家直接用局域网 IP 访问不就好了?自己给自己找麻烦
    tankren
        11
    tankren  
       2021-02-26 09:27:00 +08:00
    如果实在记不住 自己做一个导航页
    locoz
        12
    locoz  
       2021-02-26 09:37:22 +08:00 via Android
    内外网访问时,端口是否相同?如果相同的话,直接在路由器端做内网 dns,然后外网通过 vpn 连接回来,百分百无感切换。
    hjylxmhzq
        13
    hjylxmhzq  
       2021-02-26 09:53:03 +08:00
    可以用 iptables 试试,如果只用网页端的话也可以做个跳转页
    Slin
        14
    Slin  
       2021-02-26 10:22:52 +08:00
    改下 host 文件不就行了吗 或者在 nas 搭建一个局域网 dns 服务
    在家你的域名会被解析成局域网 ip,如果你就固定一台电脑使用 直接改 hosts 就行了
    Slin
        15
    Slin  
       2021-02-26 10:26:36 +08:00
    看了你后面说的问题,我没有遇到过, 你在切换网络环境 用 dig 命令, 测试下域名解析情况
    Slin
        16
    Slin  
       2021-02-26 10:30:57 +08:00
    @tankren 这种需求很常见,如果你使用 客户端填写 服务的访问地址,你就需要使用域名,内外网环境切换方便,不一定是 用在浏览器。
    la0wei
        17
    la0wei  
       2021-02-26 10:45:38 +08:00
    我有类似的经验,前两天刚刚搞定。家里的 n2n 今早挂了,无法连上去看配置,我回忆下配置。
    需要的设备:能自定义 hosts 的路由器一台,linux 设备一台或 linux 虚拟机,nas 如果能安装 haproxy 也行。

    路由器配置:192.168.1.10

    linux 设备:安装 haproxy,frontend 中 bind 端口 12345 。backend 中 server 指向 192.168.1.10:5001

    原理:访问 nas.example.com:12345 时,路由器解析到 linux 设备的 ip,而该 ip:12345,则是反代的 192.168.1.10:5001 。

    优势:无需改其他设备的配置,比如端口之类的。上面几个回答都解决了 ip 的问题,但是没解决端口的转换。
    la0wei
        18
    la0wei  
       2021-02-26 10:47:02 +08:00
    #17 有误,应为 路由器配置:192.168.1.10 nas.example.com
    la0wei
        19
    la0wei  
       2021-02-26 10:49:02 +08:00   ❤️ 1
    另外说一句,你画的 ppt 还怪好看的
    tankren
        20
    tankren  
       2021-02-26 11:18:53 +08:00
    @Slin #16 那倒是 不过楼主这种情况只能统一局域网端口和转发端口然后加上网关 DNS 覆盖才能比较完美的实现 有些人性化的客户端可以配置两套服务端信息 当连入指定 WiFi 时走局域网 IP
    jim9606
        21
    jim9606  
       2021-02-26 11:19:52 +08:00
    如果不满意 dns 劫持的效果,我建议用 iptables dnat+snat,不过企业路由能不能支持类似功能我是不清楚了。

    不过你用群晖的话 QuickConnect 好像就可以自动判断是否处于内网并自动做 301 跳转。通过浏览器 js 进行检测。
    Maskeney
        22
    Maskeney  
       2021-02-26 11:35:18 +08:00 via Android
    iptables 之类的方式劫持你的公网小鸡 IP 重定向到局域网 IP 上
    Lemeng
        23
    Lemeng  
       2021-02-26 11:43:36 +08:00
    可以,画拓扑图的点个赞
    la0wei
        24
    la0wei  
       2021-02-26 11:49:50 +08:00
    @tankren 我的方案优点在于用户对修改无感知,低门槛。建导航的方法也是极好的,对习惯用浏览器的用户比较友好,但是对客户端要求比较高。
    我为何研究这个方案,因为之前我有加速下载的需求,奈何 http 不能很好的利用我宽带的多拨叠加带宽,而 http 下载工具支持镜像功能的很少,还需要大量的手工操作,忒麻烦,才催生出这套方案。
    靠手工配置确实可以解决问题,但是都太麻烦了,还是中心化的解决方案比较方便,一劳永逸。
    另外我的方案和导航式的并不矛盾,可以很多好的融合
    piku
        25
    piku  
       2021-02-26 13:20:58 +08:00
    问题我懂了。但下面回复的我没理解。
    在家里还是用的域名吧。域名还是指向的公网 ip 吧。这就是简单的内网域名访问回流问题啊。
    在家里网关路由器上做两条。先 dst-nat 把访问公网 ip:端口的重定向到内网 ip:端口。
    然后 src-nat 把这部分流量 masquerade,否则回流有问题。
    有的路由器直接有内网服务器选项,自己能处理回流。
    hanguofu
        26
    hanguofu  
       2021-02-26 15:17:43 +08:00 via Android
    请问如何在 局域网内输入自定义的名字就可以访问同一个局域网内的其它设备啊?
    tankren
        27
    tankren  
       2021-02-26 16:07:50 +08:00
    @la0wei #24 我自己也是用的 pfsense+HAproxy 用了好几年了 问题是楼主没有公网
    la0wei
        28
    la0wei  
       2021-02-26 17:26:46 +08:00
    @tankren #52 没有公网不影响吧。公网访问楼主已经自己实现了,你看原文。内外网原理是一样的,细微差别而已。
    1.公网是公开的 dns 解析,内网是路由器自定义 hosts 实现,两者都实现了域名到 ip 的转换。
    2.端口部分,我猜楼主用的是 frps:内网有个客户端,主动连接外网服务端保活,服务端转发到客户端实现对内网的访问。frps 和 haproxy 不深入探究原理的话,在这个例子里最根本的区别在于 frps 是反弹式的。

    具体实现是否有问题还是看楼主操作后再看看。

    有一个情况我觉得建导航的方式也是非常不错的,甚至部管端口,不一样就不一样。别在在手机上访问时没关流量,看电影把房子送给移动了。内外网有显著差异还是不错的,能提醒自己切换网络。
    la0wei
        29
    la0wei  
       2021-02-26 17:28:49 +08:00
    @tankren @piku 这个解释也是靠谱的
    joesonw
        30
    joesonw  
       2021-02-26 18:20:55 +08:00
    路由器 ip tables.
    la0wei
        31
    la0wei  
       2021-02-26 18:54:14 +08:00
    @tankren @piku 确实非常接近典型的 nat 回流问题,也启发了我。区别在于楼主的情况还是有不一样的,他没有公网 ip,防火墙 /路由器默认的的 nat 回流设置需要替换外网 ip 地址,需要设备支持命令行及 iptables

    在路由器有公网 ip 的情况下,可以充分利用设备特性,此时不需要添加任何设备,不需要任何命令,全图形化操作。

    tp-link 企业级路由器示例:问题描述及解决方法 https://blog.csdn.net/x55x5/article/details/86146915

    不过 nat 回流只解决了 ip 的问题,没解决端口。不过咱可以修改内网端口,内网改成 12345 就好 https://serverfault.com/questions/592254/how-to-configure-synology-to-use-only-standard-http-ports-80-and-443-instead-of

    路由器没有公网 ip 的情况下,我建议路由器自定义 hosts,同时修改群晖端口为 12345 。
    这个方案应该是最精简的了。不需要添加任何设备,不需要任何命令行操作,避免了设备限制(自定义 hosts--路由器大概率支持,修改端口--群晖大概率支持)。

    最终结论:路由器自定义 hosts,同时修改群晖端口为 12345
    no1xsyzy
        33
    no1xsyzy  
       2021-02-27 14:10:09 +08:00
    话说,DHCP 下发路由表,使得公网 IP 导向群晖,然后在群晖上添加这个 IP (使得它收到 DST=IP 的包的时候自己消费掉),这也可行吧,就是挺邪门的。

    甚至流量不用经过路由器?
    no1xsyzy
        34
    no1xsyzy  
       2021-02-27 14:12:14 +08:00
    @no1xsyzy 哦,发现一个问题,那样的话内网包括 frpc 都连不上公网的那个 IP 了
    no1xsyzy
        35
    no1xsyzy  
       2021-02-27 14:16:25 +08:00
    @la0wei #28 结合到说室内忘记关流量的问题,我觉得 VPN 回家是最好的。
    在家里,移动设备直接关掉 VPN 。
    dorothyREN
        36
    dorothyREN  
       2021-02-27 17:09:23 +08:00
    是什么原因让你认为高位端口就安全了
    julyclyde
        37
    julyclyde  
       2021-02-27 18:49:25 +08:00
    如果端口相同且本来要访问的那个 IP 地址不变的话
    直接在网关加路由,目标为本来要访问的,下一跳为实际访问的,然后在实际访问那个服务器上增加那个本来要访问的 IP 地址就行了
    你需要考虑的是怎么搞到人家的 SSL 证书
    la0wei
        38
    la0wei  
       2021-02-27 20:22:58 +08:00
    @julyclyde 楼主的群晖默认访问端口是 5000( http)、5001( https),这是群晖出厂的默认配置,应该是内置的证书。haproxy 的 tcp 模式可以直接使用目标服务器的 ssl 证书,本地不需要特别的配置,这也是我推荐 haproxy 最主要的原因。
    @no1xsyzy 手工配置还是挺香的,我倒又产生个想法,如果经常电脑访问,透明的方式比较好,app 访问多的话,完全可以装两个功能类似的 app 做隔离。
    julyclyde
        39
    julyclyde  
       2021-02-27 22:46:53 +08:00
    @la0wei 用 haproxy 也同样存在证书和地址对不上的问题。这不是怎么转发的问题,而是转发之后怎么识别的问题
    la0wei
        40
    la0wei  
       2021-02-27 23:09:18 +08:00
    @julyclyde 根据我个人非常浅薄的经验,没有遇到证书的问题。我在外网有个服务器,使用 cloudflare 反代,内网将域名指向一台 linux 设备,并在 linux 上使用 haproxy 转发。
    PC-->局域网 haproxy-->cloudflare-->服务器

    对于 let'encrpt 证书可能会出现问题,因为确实 ip 和地址不一致,但我认为可能出问题的是在签发阶段,ip 和域名不匹配,这个很容易理解。而签发完成后,证书是否能够用在别的服务器上,这点我就不清楚了。毕竟证书只关乎公私钥,ip 是否严格限制就不知道了。而 cloudflare 证书实测可行。

    但我理解 haproxy 只是转发 tcp,证书还是从服务器获得的,对于局域网来说依然是原始 ip 和证书,出问题的可能性不大。

    我内网没有类似群晖已经签发 https 证书的设备,暂时无法测试可行性。
    dLvsYgJ8fiP8TGYU
        41
    dLvsYgJ8fiP8TGYU  
    OP
       2021-02-28 01:55:59 +08:00
    感谢各位 V 友的回复!

    家里是没有公网 IP,要不到,而且看到有人被识别所谓私设 web 被停宽带了……
    我使用的是 nps/npc ( https://github.com/ehang-io/nps) 实现的端口转发,客户端运行在 NAS Docker 上。
    证书使用的是付费证书,一年不到 10 美金,可以接受。而且 Lets Encrypt 的 OCSP 由于众所周知的原因不好使(直接影响通过手机上 Synology App 连接 NAS 的速度,当时查了好久最终发现是 LE 的 OCSP 挂了,换了个证书立马解决)

    查看了路由器设置菜单,在「基本设置」-「 DNS 设置」-「静态域名映射」中新增了一条,将云服务器的域名映射到 NAS 所在 LAN IP,并在群晖的 Application Portal 中新增一条规则将 localhost:12345 指向 localhost:5001 (HTTPS)。

    确实可以在手动切换 4G - Wi-Fi 的测试中,实现(基本)无感的切换,并且不会出现证书报错;从外面回到家里的过程中切换效果如何还有待观察。

    通过 nslookup 和观察 DNS 缓存,基本可以确定路由器「静态域名映射」的实现方式也是和 AdGuard 类似的 DNS “劫持”。至于为什么在路由器端实现 DNS 劫持的效果比 AdGuard 稍微好一点?推测是由于我当时为了防止在 NAS 中 Docker 里运行的 AdGuard 突然挂掉,导致全家断网,在路由器 DHCP 页面填了 2 个 DNS 服务器地址:
    - AdGuard (主用)
    - 路由器(备用)
    然后由于 TP-LINK 路由器某种不知名的 DNS 查询机制使得在路由器上实现要好于在 AdGuard 新建一条自定义解析??

    关于安全问题:
    @f165af34d4830eeb @julyclyde 感谢你们指出 高位端口 != 绝对安全,这一点我也深有体会。

    大概是 1 年前有人扫到了我的 web page 然后试图通过枚举 admin 的密码,触发了群晖的安全机制,把 Docker 所在的 IP (172.*.*.*) 给 ban 掉了,导致彻底无法从外面访问,后来回家看日志发现了攻击痕迹。但 nps 不支持把公网访问者的真实 IP “传递”给客户端,也就是说从群晖的防火墙看来,这次是有人试图从本地 IP (172.*.*.*) 登录系统。

    当然我后来通过查看云服务器上的 log 看到了攻击者的 IP,属于某欧洲国家,后来直接在云服务器防火墙把整个 CIDR 都给 block 了(反正我大概这辈子不会去那个地方)。后来也是考虑只允许来自中国大陆的 IP 通过云服务器访问,奈何 套路云 的防火墙面板不支持通过 ASN / Geo-IP 这些参数设置,只能手打 IP/CIDR (还是 cloudflare 好),遂放弃。反正一年碰不到几次攻击,大不了换个端口也能消停好久,也就是把家里不超过 10 台设备修改一下配置,改动成本不大。


    TP-LINK 路由器似乎没有 ip tables 设置选项,手头上有台装了 PfSense 的软路由,这几天打算研究一下

    @la0wei
    @Sylv
    @tankren
    dLvsYgJ8fiP8TGYU
        42
    dLvsYgJ8fiP8TGYU  
    OP
       2021-02-28 01:58:43 +08:00
    @julyclyde 不好意思似乎是 @错人了
    @dorothyREN 见上一条,高位确实不等于安全
    tankren
        43
    tankren  
       2021-03-01 09:36:32 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2019 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 00:52 · PVG 08:52 · LAX 16:52 · JFK 19:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.