V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
supermama
V2EX  ›  程序员

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

  •  
  •   supermama · 8 天前 · 2035 次点击

    我有一个网站,目前是通过路由做了 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  
       8 天前
    nginx 获取用户真实 ip 地址与服务器(内网公网) ip 地址校验
    当客户真实 ip 地址和服务器(内网公网) ip 地址相同,此时客户在内网
    是否可以这样
    Vraw5
        2
    Vraw5  
       8 天前
    内网通过内网 IP 访问,外网通过外网 IP 访问,得到的来源 IP 不同,可以根据来源 IP 做限制。

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

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

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

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

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

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

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