V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
supermama
V2EX  ›  程序员

有认证的登陆的网页,如何限制用户的从外网访问网页,只允许部分用户从外网访问 web

  •  
  •   supermama · 57 天前 · 2422 次点击
    这是一个创建于 57 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个网站,目前是通过路由做了 nat 映射,允许用户通过外网直接访问网站,用户也可以在内网通过访问公网的 IP 来访问这个网站。 现在我想添加一个限制: 用户如果是在外部网络(如果是通过 vpn 也认为是内网)访问这个 web 网站,检查数据库中该用户是否允许通过外网来访问网站,如果允许则放行,不允许则拒绝。 目前我是这样处理的: 1 ) web 后端添加一个 api /auth ,前端在 login 网站前先通过这个 api 的私有地址访问这个 api ,如果访问得到证明这个用户目前在内网,反之在外网。并且将 auth 返回的 token 记录在前端 2 )在执行 /login 的时候,将 token 携带到 login 的请求头, 后端收到这个请求头,如果含有这个 token 就可以判断用户是否在外网了

    存在的问题: 由于访问 /auth 用的是私有地址,但访问 web 网站用的是公有 ip ,导致会涉及到跨域访问,目前 chrome 浏览器做了安全限制,需要将私有地址手动的添加到允许访问列表。 但是我们目前想让用户无感,最好用户什么都不需要操作。所以想请问下,是否有其它更好的方案,对用户使用无感的操作,当用户在访问 web 的时候就能准确知道用户是否在内外网,便于下一步的权限控制。

    24 条回复    2024-10-29 16:47:30 +08:00
    Latin
        1
    Latin  
       57 天前
    nginx 获取用户真实 ip 地址与服务器(内网公网) ip 地址校验
    当客户真实 ip 地址和服务器(内网公网) ip 地址相同,此时客户在内网
    是否可以这样
    Vraw5
        2
    Vraw5  
       57 天前
    内网通过内网 IP 访问,外网通过外网 IP 访问,得到的来源 IP 不同,可以根据来源 IP 做限制。

    内网将域名 DNS 解析成内网 IP ,这样来自内网的全部放过,无需判断。如果改不了,内网的出口 IP 一般是固定的,后端默认来自这个公网 IP 的为内网登录,全部放过。

    非上述来源 IP 的,登录时判断是否允许外网登录
    kiracyan
        3
    kiracyan  
       57 天前
    登陆时,访问一个内网 API ,验证成功就是内网,无法验证就是外网
    N0vermber11
        4
    N0vermber11  
       57 天前
    听起来像是 vpn 的使用场景
    litchinn
        5
    litchinn  
       57 天前
    从你的问题描述我感觉你是有 PNA 问题,公网访问服务后无法发起请求到/auth 端点,被 chrome 拦截了,所以没法通过这个接口判断
    https://www.cnblogs.com/lizhigang/p/18008373
    这文章说可以通过 https 解决,但我没试过,不是很了解
    楼上说的 ip 过滤也是一种办法
    shuyunquan
        6
    shuyunquan  
       57 天前
    之前搞过就是 IP 白名单, 内网的 IP 存储起来, 网页写个中间件,凡是请求 IP 不在白名单的统一禁止
    Foxkeh
        7
    Foxkeh  
       57 天前
    Nginx 反向代理, 加入以下参数定义
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    (不建议用$remote_addr, 这样多层 Nginx 反代后识别到的用户 IP 不准确)

    假设是否允许公网登录存储在用户表, 那么在用户登录时, 加入一层逻辑校验: 后端从请求头获取上面的参数, 分析用户 IP, 按照, 内网 IP 放行, 公司的出口 IP 放行, 其他 IP 判断用户是否有外网允许登录标记即可.
    supermama
        8
    supermama  
    OP
       57 天前
    @Latin 你这种场景只适合企业只有一条专线的情况(用户的 pc 和服务器都是走的专线,两者访问网络的时候都是转化为固定 ip) 。 但是目前我们服务器是固定 ip(专线) ,其它的 pc 用户走的是动态 ip ,以至 pc 用户的外部 ip 一直在变化。 没办法简单的通过这种 ip 相等去判断是否是在内网访问。
    supermama
        9
    supermama  
    OP
       57 天前
    @kiracyan 现在就是这么做的,涉及到跨域,客户访问的时候有感。所以想换一个无感的方案。
    supermama
        10
    supermama  
    OP
       57 天前
    @litchinn 是的,目前我就是用这个方案去访问。 最大的问题是,用户第一次要手工点击,允许这个域名访问。 变成第一次需要用户手工介入,将这个域名纳入白名单,后续才能正常使用。
    supermama
        11
    supermama  
    OP
       57 天前
    @Foxkeh 你这个方案可行,但是我目前比较特殊: 我的服务器是固定 ip (一个专线)、pc 用户走的另外一根动态 ip 的线。两根线都插在同一个网关,所以两者其实也是属于一个内网。 按你的方法,其实是判断不出来,或者说现在的 pc 用户会被判断成是在外网访问。
    supermama
        12
    supermama  
    OP
       57 天前
    @Vraw5 感觉可以,但是这个要怎么配置呢? 我前端是用 vue 写的,一般就是把域名配置到 vue 代码里面去了,访问的时候 dns 动态区分映射出来的 ip 是公网还是私网 ip 。 但如果用户是拿着笔记本一会儿在内网,一会儿在外网要怎么处理。 另外 nginx 那边收到的用户请求是不是都是访问的是域名,而不是访问的 ip ,这个在 nginx 要怎么配置呢?
    Vraw5
        13
    Vraw5  
       57 天前
    @supermama #12 域名在代码里正常配置,搭个 DNS 给公司 WIFI(以及 vpn)用,公司 WIFI 用这个 DNS ,这个域名的解析就是内网 IP ,连其他 WIFI 时的解析就是外网 IP 。

    nginx 那边可以通过#7 楼的方法获取到真实 IP 并传给后端,后端读 header 能拿到真实 IP

    如果搭 DNS 费劲,可以直接禁掉外网登录的需求,全部改为内网登录。在公司的不谈,在外的使用 vpn 连接后访问。这样可以直接让他们在 hosts 里写死解析
    Atma
        14
    Atma  
       57 天前 via Android
    vpn 那边权限限制
    webszy
        15
    webszy  
       57 天前   ❤️ 2
    已经有认证了,直接限制登陆用户就行了,何必脱裤子放屁
    catamaran
        16
    catamaran  
       57 天前
    你先理清楚,怎么判断是不是内网用户,如果人脑从逻辑上都区分不了,电脑也起不到啥作用。
    supermama
        17
    supermama  
    OP
       57 天前
    @catamaran 你看我正文里面,我是直接去访问 一个 192.168.0.xx/auth 的接口,如果是内网肯定是可以通的,外网不行。 只不是这种会跟我正常的网站 www.xxx.com 访问,会有跨域的冲突,用户需要将 192.168.0.xx 这个 ip 手工加入白名单。我不想让用户手动加白名单这个动作。
    catamaran
        18
    catamaran  
       57 天前
    @supermama #17 所以方案只有你说的这种。如果是问题是跨域访问,有成熟的方案,像以前的 jsonp ,或者 http head 做一些限制(我不是很了解这块)。我不明白你说的这个白名单指什么?是在浏览器配置里操作吗?
    xinzhanghello
        19
    xinzhanghello  
       57 天前
    cf WAF + static html apply + IP whitelist
    NSAgold
        20
    NSAgold  
       57 天前 via Android
    cors 跨域我记得有个 access-control-allow-credentials 是可以带 cookie 的
    或者内网 DNS 把内网访问 ip 解析成服务器内网 ip 然后 nginx 内外网不同策略处理
    再或者你给 token 的接口挪到主站来,内网地址负责 302 到这个接口,外网访问用户没有 302 访问不到这个接口
    chobitssp
        21
    chobitssp  
       57 天前
    做个 electron 应用(也可以是别的) 让客户先安装 前端通过应用判断是否内网
    lisongeee
        22
    lisongeee  
       56 天前
    私有网络访问限制 https://developer.chrome.com/blog/private-network-access-update?hl=zh-cn

    最无感的方式是买个域名后控制台解析 A 记录到 192.168.0.xx ,申请 ssl 证书,直接用 https 访问

    你的现有操作都是在 http 上下文,它就是有很多限制,直接升级到 https 就完了呗
    cat1879
        23
    cat1879  
       56 天前
    我以前弄类似的,感觉你这个需求和我当年类似。我这个是内网不限制,外网访问时加个扫码或者 auth 的认证。认证的 IP 允许一段时间进行访问
    supermama
        24
    supermama  
    OP
       56 天前
    @cat1879 是的,内网不限制,只限制外网。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3034 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:14 · PVG 22:14 · LAX 06:14 · JFK 09:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.