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

4 天前
 supermama

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

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

1919 次点击
所在节点    程序员
24 条回复
Latin
4 天前
nginx 获取用户真实 ip 地址与服务器(内网公网) ip 地址校验
当客户真实 ip 地址和服务器(内网公网) ip 地址相同,此时客户在内网
是否可以这样
Vraw5
4 天前
内网通过内网 IP 访问,外网通过外网 IP 访问,得到的来源 IP 不同,可以根据来源 IP 做限制。

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

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

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

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

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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1084126

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX