Linuxword Global
当前位置: 通信协议 > 搭建麦当劳店里自带认证功能的wifi及自定义认证逻辑

1460000023361006

日常生活中常能碰到一些商场或餐饮店提供一种需认证的wifi,这种wifi连接后不能立刻使用,往往还需要在一个页面上进一步认证操作才行,比如输入手机号填个验证码之类的。

作为一名前端开发,每当我去麦当劳店里吃饭,用手机连接wifi时,一直都很想搞清楚几个问题:

  • 这种wifi认证页面是如何搭建的?
  • 它的认证机制是怎样的?
  • 它跟正常的网站会有哪些不一样?

这种wifi的英文学名叫Captive Portal,在开源社区中早已存在一些组件可轻松搭建这种类型的wifi,比如wifiDog, CoovaChilli, nodogslash等。

为了一探究竟,我用nodogslash在树莓派上搭建了一个带认证功能的wifi,并且使用React创建了自定义认证页面,尝试搞清楚整个认证流程背后的原理。

最终呈现的页面效果如下,点击按钮即完成认证:

wifi认证的机制和原理

每当设备连接wifi后,系统会自动做一个连通性校验,此校验的本质是发送一个HTTP请求。如果请求失败,则会触发相应机制要求用户输入登录凭证。如果请求成功,则表示网络已通,无任何回应,这个网络校验过程叫Captive Portal Detection (CPD)。

不同的操作系统校验时的请求地址不一样,比如我用手边的android和iphone手机分别做了测试,他们对应校验地址如下:

  • http://connectivitycheck.smar... (坚果 pro3)
  • http://captive.apple.com/hots... (iphone 6)

简单来说,wifi的认证过程通过一个HTTP GET请求即可完成。以我本文示例中使用的nodogsplash组件为例,其内部用C语言实现了一个服务器运行在2050端口。设备连上wifi时,wifi端会生成一个token,当设备被重定向到认证页面时,页面模板中包含此token,此时用户只需发送一个GET请求将此token传入到对应服务器的认证地址即可。

如果你配置了FAS,也就是说设置了自定义认证机制,比如说你想添加了一个手机验证环节,需要用户填入手机和验证码才能完成认证。那么nodogsplash在重定向登录页面的时候会把一些重要参数附带在请求地址的后面,让你的自定义入口页能获取到这些认证凭证,比如token之类的参数。

等你的自定义验证手机验证通过了,再选择将token以HTTP GET请求发送回原2050端口上的认证服务器,整个流程如下图所示:

认证站点的限制

需要注意的是,当用户设备连上wifi但还尚未通过验证时,网络访问是受限的,此时能访问的内容取决于防火墙的设置。比如我上面示例中,将站点配置在路由器上,网站端口是8080,依赖的后端服务器运行在端口8081上,此时必须在nodogsplash的防火墙规则中开放这两个端口,才能让未认证的用户设备访问的到。假如服务器配置在外网,就要将对应的域名或IP在防火墙中开放出来,具体配置方式参考nodogsplash关于FAS的文档。

另外,wifi认证页面的实现上要有一些额外的安全考量。比如在nodogsplash的官网文档中建议网站遵循一下安全准则:

  1. 当认证成功后需立刻关闭浏览器
  2. 禁止使用链接
  3. 禁止文件下载功能
  4. 禁止执行javascript

关于第二条,可以使用表单提交的方式替换链接调整,而对于第四条,它的本意并不是禁止js功能,只是为了防止执行js语句引起的安全性问题。我在示例中搭建的网站使用了react框架,在android和ios上都能正常显示。

因此,在功能实现上相比较通常的前端站点,自定义的wifi认证网站部分功能受限,但影响并不大,可以使用你自己擅长的前端框架来搭建。

创建需认证的wifi

注意,如果你手边没有树莓派或Linux系统,或者对配置部分不感兴趣,直接跳过即可。

准备工作

  • 树莓派 4B
  • hostapd和dnsmasq (用于创建wifi热点)
  • nodogsplash (核心组件,管理wifi热点,提供认证功能)

nodogsplash可以安装OpenWrt和Linux中,前者是开源的智能路由器操作系统,国内的一些路由器厂商通常是基于此系统定制的,后者就不必多介绍了,这次的示例就是安装在Linux系统上,为了方便安装调试,我直接使用一个树莓派4作为载体,用网线连通网络,用无线创建热点wifi。

创建wifi热点

在安装组件之前,首先将依赖包更新,然后安装hostapd和dnsmasq两个组件,前者用来创建wifi热点,后者用来处理DNS和DHCP等服务。

sudo apt-get update
sudo apt-get upgrade

sudo apt-get install hostapd dnsmasq

修改配置并指定一个wifi网段,配置文件在/etc/dhcpcd.conf

sudo vi /etc/dhcpcd.conf

# ...

# 文件内容如下:
interface wlan0
    static ip_address=192.168.220.1/24
    nohook wpa_supplicant

其中wlan0是无线网卡的名称,可以通过ifconfig命令查询,IP地址可任意指定,只要不跟家中的wifi冲突即可,比如说此处设置的是192.168.220.*,而我家中的wifi网段是192.168.31.*。

重启一下服务,让配置生效:

sudo systemctl restart dhcpcd

修改hostapd配置,用于设置wifi的名称和密码,其中ssid表示此wifi的名称,wpa_passphrase表示此wifi的密码。

sudo vi /etc/hostapd/hostapd.conf

# ...

# 文件内容如下:
interface=wlan0
driver=nl80211

hw_mode=g
channel=6
ieee80211n=1
wmm_enabled=0
macaddr_acl=0
ignore_broadcast_ssid=0

auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

# wif的名称
ssid=Pi4-AP
# wifi的秘密
wpa_passphrase=pimylifeup
修改配置文件/etc/default/hostapd

这时还需要再修改两个配置文件,一个是hostapd启动时的加载文件,需要将配置文件字段DAEMON_CONF指定为上面的文件地址,默认情况下该字段是被注释掉的。

sudo nano /etc/default/hostapd

# ...
# 文件内容如下:
# 将#DAEMON_CONF="" 修改为下面这行
DAEMON_CONF="/etc/hostapd/hostapd.conf"
修改配置文件/etc/init.d/hostapd

另一个配置文件是系统服务配置,同意将上文的配置文件地址赋值给DAEMON_CONF字段。

sudo vi /etc/init.d/hostapd

# ...

# 文件内容如下:
# 将DAEMON_CONF=修改为下面这行
DAEMON_CONF=/etc/hostapd/hostapd.conf
修改配置文件/etc/dnsmasq.conf

在此文件配置自定义wifi的网段、dns服务器等信息。

sudo vi /etc/dnsmasq.conf

# ...

# 文件内容如下:
interface=wlan0       # 指定无线网卡名称 
server=114.114.114.114       # 使用dns服务器
dhcp-range=192.168.220.50,192.168.220.150,12h  # 指定可用IP的网段范围和释放时间
无线网卡转发有线网卡

修改系统配置文件中的net.ipv4.ip_forward字段,激活转发功能,默认情况下,该字段是被注释掉的。

sudo vi /etc/sysctl.conf

# ...

# 文件内容如下:
# 将原#net.ipv4.ip_forward=1的注释符号去掉,修改为下面这行
net.ipv4.ip_forward=1

重启系统,让此修改生效。

sudo reboot

然后,通过iptables命令实现网卡之间的信息转发,其中eth0是有线网卡的名称,可通过ifconfig命令查询。

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

最后,需要将当前iptables的配置保存下来,保证每次机器重启时该配置都能生效,先将配置保存到文件中/etc/iptables.ipv4.nat。

# 将配置写入/etc/iptables.ipv4.nat文件
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

修改rc.local,保证每次启动时都会读取iptables配置。

sudo vi /etc/rc.local

# ...
# 文件内容如下:

# ...
# 在“exit 0”这一行之前添加下面命令读取iptables的配置
iptables-restore < /etc/iptables.ipv4.nat

exit 0
启动wifi热点

最后,关于热点的配置终于配置完毕,运行一下命令启动服务:

sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd
sudo service dnsmasq start

这时,应该可以用手机检测到配置的wifi出现了Pi4-AP,该名称即上面配置的wifi名称,输入对应密码即可连上网络。此时可重启一下再连,确保重启后配置依然生效。

sudo reboot

安装nodogsplash

首先安装对应依赖git和libmicrohttpd-dev。

sudo apt install git libmicrohttpd-dev

然后使用git直接将nodogsplash源码拿下来,直接安装。

git clone https://github.com/nodogsplash/nodogsplash.git
cd ./nodogsplash
make
sudo make install

添加nodogsplash配置

添加配置到文件/etc/nodogsplash/nodogsplash.conf中,指定对应网卡、网关、最大连接用户数和认证过期时间。其中,wlan0是上面配置的无线网卡名,IP地址是上面配置的wifi热点的网关。

sudo vi /etc/nodogsplash/nodogsplash.conf

# ...

# 文件内容如下:
GatewayInterface wlan0
GatewayAddress 192.168.220.1
MaxClients 250
AuthIdleTimeout 480

配置完成后,启动nodogsplash。

sudo nodogsplash

此时,用手机连接创建的wifi并输入密码以后,即可看到以下弹窗,要求登录认证。

1460000023361012

点击登录后进入认证页面。

配置自定义wifi认证页面

nodogsplash本身提供了自定义验证机制 - Forwarding Authentication Service (FAS),它可以指定自定义的认证页面和认证方式,通过简单配置对应服务器的IP和端口即可。

比如,我在同一台机器上开启一个react站点,端口为8080,若想把此站点设置为认证入口页,只需在配置文件中添加下面四行代码即可,其中fas_secure_enabled有从0到3的多个等级值,从低到高会让安全性和复杂性递增,此处选了最简单等级用于做演示。

sudo vi /etc/nodogsplash/nodogsplash.conf

# ...

# 要添加的内容如下
fasport 8080
fasremoteip 192.168.220.1
faspath /
fas_secure_enabled 0

最后,呈现的样子如下,点击按钮即完成认证,顺利联网。

1460000023361011

备注:关于nodogsplash的版本

nodogsplash源码中的master分支指向的3.3.5版本,而此时最新版是5.0.0(笔者写此文章时间2020.7),越新的版本其文档越完善,但要注意的是4.5.1版本是一个分水岭,因为从4.5.1之后该项目的自定义登录授权功能被剥离到一个独立项目openNDS。

假如切换到v4.5.1版后碰到libmicrohttpd报组件过时异常,可在配置文件中添加字段se_outdated_mhd 1避开此异常。

1460000023361009

结语

带认证的wifi在商业活动中越来越常见,开源社区中,nodogsplash是其中一种实现方式,在少量限制的情况下,提供了足够的灵活性让你用熟悉的方式像搭建其他网站一样搭建wifi认证页面。最终,把你的前端能力延伸到路由器上。

「梦想一旦被付诸行动,就会变得神圣,如果觉得我的文章对您有用,请帮助本站成长」

赞(0) 打赏
一分也是爱

支付宝扫一扫打赏

微信扫一扫打赏

上一篇:

下一篇:

相关推荐

博客简介

本站CDN采用VmShell免费提供离中国大陆最近的香港CMI高速网络做支撑,ToToTel打造全球最快速的边沿网络支撑服务,具体详情请见 :https://vmshell.com/ 以及 https://tototel.com/,网站所有的文件和内容禁止大陆网站搬迁复制,谢谢,VPS营销投稿邮箱: [email protected],我们免费帮大家发布,不收取任何费用,请提供完整测试文稿!

精彩评论

友情链接

他们同样是一群网虫,却不是每天泡在网上游走在淘宝和网游之间、刷着本来就快要透支的信用卡。他们或许没有踏出国门一步,但同学却不局限在一国一校,而是遍及全球!申请交换友链

站点统计

  • 文章总数: 2306 篇
  • 草稿数目: 12 篇
  • 分类数目: 6 个
  • 独立页面: 0 个
  • 评论总数: 2 条
  • 链接总数: 0 个
  • 标签总数: 5836 个
  • 注册用户: 139 人
  • 访问总量: 8,647,960 次
  • 最近更新: 2024年4月2日