主要的参考来源
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/9/html/configuring_and_managing_networking/assembly_setting-up-an-802-1x-network-authentication-service-for-lan-clients-using-hostapd-with-freeradius-backend_configuring-and-managing-networking
环境条件
一台刷入openwrt系统的路由器担当交换机 接入一套网络系统中
该 "交换机"的一个lan口接入 主路由
其他终端如pc电脑 有线接入该 交换机 的lan口
网络拓扑图
1 openwrt配置为交换机
由于openwrt交换机系统为18.06.5 默认使用vlan 将每个lan口组为hub 集线器,这样是高效转发的,报文直接在物理层转发,不会进入cpu,但这样也意味着无法使用ebtables拦截报文,为了实现802.1x拦截作用,需要移除vlan,使用bridge网桥,将几个lan口桥接到一起,而报文能进入cpu,使得ebtables能够拦截
默认vlan配置
vlanid CPU (eth0) LAN 1 LAN 2 LAN 3 LAN4 WAN
1 已标记 未标记 未标记 未标记 未标记 关
2 已标记 关 关 关 关 未标记
-
删除 vlan1
-
为每个lan口各自创建一个vlan vlanid 如 11 12 13 14
-
删除默认的br-lan
-
新建接口 lan
dhcp协议 或 其他协议如静态地址 这样当前openwrt设备可以被访问
Create a bridge over multiple interfaces 勾选
cover the following interface 选择上述创建的 vlan11到14 也就是eth11 12 13 14 -
/etc/config/network 配置如下
config switch_vlan
option device ‘switch0’
option vlan ‘3’
option ports ‘0 6t’
option vid ‘11’
config switch_vlan
option device ‘switch0’
option vlan ‘4’
option vid ‘12’
option ports ‘1 6t’
config switch_vlan
option device ‘switch0’
option vlan ‘5’
option vid ‘13’
option ports ‘2 6t’
config switch_vlan
option device ‘switch0’
option vlan ‘6’
option vid ‘14’
option ports ‘3 6t’
config interface ‘lan’
option type ‘bridge’
option proto ‘dhcp’
option ifname ‘eth0.11 eth0.12 eth0.13 eth0.14’
config interface ‘lan6’
option ifname ‘@lan’
option proto ‘dhcpv6’
option reqprefix ‘auto’
配置完毕重启network
2 hostapd的wired支持
在openwrt18.06.5 hostapd默认没有带CONFIG_DRIVER_WIRED=y编译选项 而在openwrt22以上已经开启该选项
同时 hostapd还可以作为简单的radius服务器
附加编译选项CONFIG_RADIUS_SERVER=y
18.06.5版本编译hostapd
cat feeds/base/package/network/services/hostapd/files/hostapd-full.config|grep -Ev ‘#|^$’
CONFIG_DRIVER_HOSTAP=y
CONFIG_DRIVER_WIRED=y
CONFIG_DRIVER_NL80211=y
#使用 radius
CONFIG_DRIVER_NONE=y
CONFIG_IAPP=y
CONFIG_RSN_PREAUTH=y
CONFIG_PEERKEY=y
#80211w保护
CONFIG_IEEE80211W=y
CONFIG_EAP=y
CONFIG_ERP=y
CONFIG_EAP_MD5=y
CONFIG_EAP_TLS=y
CONFIG_EAP_MSCHAPV2=y
CONFIG_EAP_PEAP=y
CONFIG_EAP_GTC=y
CONFIG_EAP_TTLS=y
CONFIG_EAP_PSK=y
CONFIG_EAP_FAST=y
#pwd 需要 crypto 库 似乎在 gnutls 没试过
#CONFIG_EAP_PWD=y
CONFIG_WPS=y
CONFIG_PKCS12=y
#radius 服务器
CONFIG_RADIUS_SERVER=y
CONFIG_IPV6=y
CONFIG_IEEE80211R=y
#基于client的MAC地址的访问控制 在认证请求帧时进行处理
CONFIG_DRIVER_RADIUS_ACL=y
CONFIG_IEEE80211N=y
CONFIG_WNM=y
CONFIG_IEEE80211AC=y
CONFIG_DEBUG_SYSLOG=y
CONFIG_FULL_DYNAMIC_VLAN=y
CONFIG_NO_DUMP_STATE=y
CONFIG_NO_RANDOM_POOL=y
CONFIG_TLS=internal
#tls1.2
CONFIG_TLSV12=y
CONFIG_INTERNAL_LIBTOMMATH=y
#移动网络和WiFi网络之间的无缝流量切换
CONFIG_HS20=y
CONFIG_FST=y
CONFIG_FST_TEST=y
CONFIG_TESTING_OPTIONS=y
#2.4g 自动选频
CONFIG_ACS=y
#http://wiki.stocksy.co.uk/wiki/Multiple_SSIDs_with_hostapd
CONFIG_MBO=y
CONFIG_TAXONOMY=y
CONFIG_UBUS=y
crypto eap-pwd 需要 但是未测试是否可用
│ Symbol: GNUTLS_CRYPTODEV [=n] │
│ Type : boolean │
│ Prompt: enable /dev/crypto support │
│ Location: │
│ -> Libraries │
│ -> SSL │
│ -> libgnutls… GNU TLS (l │
│ (2) -> Configuration │
│ Defined at feeds/packages/libs/gnutls/Config.in:18 │
│ Depends on: PACKAGE_libgnutls [=m]
进入全选 * 出来选M
make -j1 V=s package/gnutls/compile
│ Symbol: OPENSSL_ENGINE_CRYPTO [=y] │
│ Type : boolean │
│ Prompt: Crypto acceleration support │
│ Location: │
│ -> Libraries │
│ -> SSL │
│ (4) -> libopenssl… Open source SSL toolkit (lib │
│ Defined at feeds/base/package/libs/openssl/Config.in:65 │
│ Selects: OPENSSL_HARDWARE_SUPPORT [=y] │
│ Selected by: PACKAGE_haproxy [=m] │
│
make -j1 V=s package/openssl/compile
得到
openssl-util_1.0.2t-1_mipsel_24kc.ipk
libopenssl_1.0.2t-1_mipsel_24kc.ipk
make defconfig
make menuconfig
hostapd 不要选中
hostapd-openssl 选 * 不选m hostapd-cli 选*
编译
make -j1 V=s package/hostapd/compile
编译的包在 bin/packages/mipsel_24kc/base
得到
wpad_2018-05-21-62566bc2-8_mipsel_24kc.ipk
移除默认 wpad-mini
使用openssl
以下按顺序
卸载 wpad
opkg remove wpad-mini
opkg remove wpad 提供完整的 eap wap wep
移除掉已经安装 的 wpad
opkg remove wpad
不要 opkg update 否则只会从网上下载不会本地安装
从/tmp 安装
opkg install /tmp/wpad-openssl_2018-05-21-62566bc2-8_mipsel_24kc.ipk
3 安装ebtables
从链路层拦截未经过802.1x认证的报文,如果那些已经经过认证的则发行
opkg install ebtables ebtables-utils kmod-ebtables-ipv4 kmod-ebtables-ipv6
另外 可选的kmod-ebtables-watchers 日志输出
测试安装成功
ebtables -V
4 网桥设置 group_fwd_mask 8
group_fwd_group默认值为0 不处理所有 01:80:c2:00:00:0X 地址的报文
802.1X Port-Based Network Access Control 链路地址为 01:80:c2:00:00:03
需要网卡类型为网桥才能设置该选项 这样才能传透 01:80:c2:00:00:03 eapol 报文
echo 8 > /sys/class/net/br-lan/bridge/group_fwd_mask
或者
ip link set dev br-lan type bridge group_fwd_mask 8
5 主要实现
通过hostapd指定wired 作为 eap port-base 访问控制器
使用 hostapd_cli -a /etc/hostapd-wired-handler.sh 通过脚本从hostapd接收到的事件类型拦截或放行报文
如
当 接收到 AP-STA-CONNECTED | CTRL-EVENT-EAP-SUCCESS|CTRL-EVENT-EAP-SUCCESS2 事件时
放行mac地址
ebtables -t filter -I FORWARD 1 --among-src 11:22:33:44:55:66 -j ACCEPT
ebtables -t filter -I FORWARD 1 --among-dst 11:22:33:44:55:66 -j ACCEPT
当接收到 AP-STA-DISCONNECTED | CTRL-EVENT-EAP-FAILURE | CTRL-EVENT-DISCONNECTED 事件时
删除 由上述创建的 放行规则
ebtables -t filter -D FORWARD --among-src11:22:33:44:55:66-j ACCEPT
ebtables -t filter -D FORWARD --among-dst 11:22:33:44:55:66 -j ACCEPT
6 掉线检测
hostapd.conf
使用 eap_reauth_period=3600
每隔一定时间 重新认证 如果客户端不在线 是不会通过认证的
在 hostapd_cli 会接收到 几次 CTRL-EVENT-EAP-RETRANSMIT
之后仍无响应 发出 CTRL-EVENT-EAP-TIMEOUT-FAILURE
然后 AP-STA-DISCONNECTED
假设主机已经离线 但规则依然保存于防火墙中, 根据 eap_reauth_period 重新认证的方法 可以触发
AP-STA-DISCONNECTED 事件 以此删除放行规则
如果客户端不通过 退出的方式终止连接 如 直接调用 wpa_cli terminate 而没有调用 wpa_cli logoff ,
hostapd_cli 不会接收到 AP-STA-DISCONNECTED | CTRL-EVENT-EAP-FAILURE | CTRL-EVENT-DISCONNECTED
这样的事件 这样意味着 该主机的mac 已经保存在ebtables ,根据 eap_reauth_period 重新认证的间隔 如果过期不认证 该主机的ebtables规则才被删除
7 持久化
在ebtables 指定 --among-src-file --among-dst-file 将mac地址保存到文件 然后根据需要添加或删除mac地址到文件
这里没有实现
考虑到 如果 当前路由器如果 使用 --among-src --among-dst 运行时规则 在重启主机后 ebtables规则会丢失
但是对客户端而言 其实也就是 再次执行一个eap认证 就是wifi那样 恢复ap热点后 会再次自动连接
8 关于组播和广播
默认情况 组播和广播是直接通过交换机,转发到每个网口的
可能导致的情况是 连接"交换机"的每个客户机 可以在未通过802.1x认证之前 而先接收到一些组播包和广播包 如 dhcp ,ipv6 igmp 出现的情况是 客户机先被分配了ip地址 但不能单播通信,因为被ebtable拦截了
如果不是追求完善 其实可以使用
但如果要解决这个问题
方法1.
白名单机制
考虑到实际连接情况 一些报文不经过"交换机"可以不为其做 802.1x认证 像组播/广播 需要传透到整个网络的
这些被允许的mac地址 可以不做802.1x认证
例如直接将dhcp服务器的mac地址 直接 写到ebtables规则
方法2.
将局域网内所有主机都进行 802.1x认证
9 hostapd.conf 配置
ctrl_interface=/var/run/hostapd-wired
ctrl_interface_group=0
#Enable logging for all modules
#logger_syslog=-1
#logger_stdout=-1
#Log level
#logger_syslog_level=2
#logger_stdout_level=2
#Driver interface type
driver=wired
#Enable IEEE 802.1X authorization
ieee8021x=1
#use_pae_group_addr=1
interface=br-lan
#bridge=br-lan
own_ip_addr=192.168.11.55
#nas_identifier=newifi-d2
auth_server_addr=192.168.11.222
auth_server_port=18012
auth_server_shared_secret=11223344
#acct_server_addr=192.168.11.222
#acct_server_port=18013
#acct_server_shared_secret=11223344
#country_code=CN
#auth_algs=3
#看数据包有无加密
#wpa_key_mgmt=WPA-EAP
#wpa_key_mgmt=WPA-PSK
#wpa_pairwise=CCMP
#rsn_pairwise=CCMP
eap_reauth_period=3600
10 将hostapd-wired 编写为init.d服务
#!/bin/sh /etc/rc.common
# /etc/init.d/hostapd-wired
START=50
boot() {
start
}
start() {
value=$(head -1 /sys/class/net/br-lan/bridge/group_fwd_mask)
value2=$value
let "value=$value&0x8"
[ $value -ne 8 ] && ( let "value=$value2|0x8" ;\
echo $value > /sys/class/net/br-lan/bridge/group_fwd_mask )
[ -e /etc/hostapd-wired.conf ] && \
hostapd -B -P /var/run/hostapd-wired.pid /etc/hostapd-wired.conf >/dev/null 2>&1
[ -x /usr/sbin/hostapd_cli ] && [ -e /etc/hostapd-wired-handler.sh ] && \
hostapd_cli -p /var/run/hostapd-wired -a /etc/hostapd-wired-handler.sh -B
}
stop() {
kill -15 $(head -1 /var/run/hostapd-wired.pid)
}
11 hostapd_cli -a 脚本 hostapd-wired-handler.sh 配置
注意 默认的ebtables规则 是 ACCPET 不是DROP
#!/bin/sh
# /etc/hostapd-wired-handler.sh
# chmod +x /etc/hostapd-wired-handler.sh
#基于 --among-dst --among-src 的实现不是 基于 --among-dst[src]-file
#set -x
#$1=adapter
#$2=event string type
#$3 src mac
#echo "new event .."
#echo "$1"
#echo "$2"
#echo "$3"
#exit 0 on succeed
mac_isvaild ()
{
MACADDR=`echo $1|grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'`
[ "$MACADDR" = "$1" ] && return 0
return 1
}
#RETURN 必须在DROP的前一行插入
#case ${2} in
case ${2:-NOTANEVENT} in
AP-STA-CONNECTED | CTRL-EVENT-EAP-SUCCESS|CTRL-EVENT-EAP-SUCCESS2)
mac_isvaild $3
if [ $? -eq 0 ]; then
[ $(ebtables -t filter -L DOT1X_FWD|grep -c -i "\--among-src $3, -j RETURN") -eq 0 ] && \
ebtables -t filter -I DOT1X_FWD 1 --among-src $3 -j RETURN
[ $(ebtables -t filter -L DOT1X_FWD|grep -c -i "\--among-dst $3, -j RETURN") -eq 0 ] && \
ebtables -t filter -I DOT1X_FWD 1 --among-dst $3 -j RETURN
logger -t efw-8021x "addr: ${3} ,event: ${2}"
fi
;;
AP-STA-DISCONNECTED | CTRL-EVENT-EAP-FAILURE | CTRL-EVENT-DISCONNECTED)
mac_isvaild $3
if [ $? -eq 0 ]; then
ebtables -t filter -D DOT1X_FWD --among-src $3 -j RETURN >/dev/null 2>&1
ebtables -t filter -D DOT1X_FWD --among-dst $3 -j RETURN >/dev/null 2>&1
logger -t efw-8021x "addr: ${3} ,event: ${2}"
fi
;;
esac
12 编写802.1x ebtables的init.d服务
#!/bin/sh /etc/rc.common
# /etc/init.d/efw8021x
START=20
#说明
#ebtables 默认策略为ACCEPT
# 在filter 表 FORWARD链 创建 DOT1X_FWD 链
#ebtables -t filter -I FORWARD 1 -j DOT1X_FWD
#需要保持 DOT1X_FWD位于FORWARD链中处于第一个规则
#将原来的br-lan删除 删除 switch 绑定 br-lan的4个网口
#为每个网卡分配独立的vlan 11 12 13 14 也就是网卡 eth0.11 eth0.12 eth0.13 eth0.14
#然后在创建 br-lan 将 这个网口桥接到一起
IFACE=eth0.1+
boot() {
start
}
start() {
#FORWARD
ebtables -t filter -N DOT1X_FWD >/dev/null 2>&1
[ $(ebtables -t filter -L DOT1X_FWD|grep -c "\-p 0x888e -j RETURN") -eq 0 ] && \
ebtables -t filter -A DOT1X_FWD -p 0x888e -j RETURN
[ $(ebtables -t filter -L DOT1X_FWD|grep -c "\-d Multicast -j RETURN") -eq 0 ] && \
ebtables -t filter -A DOT1X_FWD -d Multicast -j RETURN
[ $(ebtables -t filter -L DOT1X_FWD|grep -c "\-d Broadcast -j RETURN") -eq 0 ] && \
ebtables -t filter -A DOT1X_FWD -d Broadcast -j RETURN
#log for debug
#ebtables -t filter -A DOT1X_FWD --log-prefix "efw8021x drop: " -j DROP
[ $(ebtables -t filter -L DOT1X_FWD|grep -c "\-j DROP") -eq 0 ] && \
ebtables -t filter -A DOT1X_FWD -j DROP
[ $(ebtables -t filter -L FORWARD|grep -c "\-i eth0.1+ -j DOT1X_FWD") -eq 0 ] && \
ebtables -t filter -I FORWARD 1 -i $IFACE -j DOT1X_FWD
[ $(ebtables -t filter -L FORWARD|grep -c "\-o eth0.1+ -j DOT1X_FWD") -eq 0 ] && \
ebtables -t filter -I FORWARD 1 -o $IFACE -j DOT1X_FWD
}
stop () {
ebtables -t filter -D FORWARD -o $IFACE -j DOT1X_FWD
ebtables -t filter -D FORWARD -i $IFACE -j DOT1X_FWD
ebtables -t filter -X DOT1X_FWD
}
这篇内容没写配置radius服务