使用wpa_supplicant连接无线网络
一直以来,我们都会使用发行版默认使用的网络配置工具来设置网络,例如Ubuntu默认使用 netplan网络配置 ,而RedHat或者其他发行版默认使用 NetworkManager 。总之,工具五花八门,特别是设置企业级无线网络WPA2,命令参数更是复杂多变。
然而,实际上不同的网络配置工具在配置无线网络时,最终生成的配置文件和使用的工具其实都是 wpa_supplicant ,所以我们也可以手工编辑 wpa_supplicant 配置文件或者使用 wpa_supplicant 命令来构建初始配置并进行进一步定制。
激活无线网卡
首先我们需要确保无线网卡是激活的,使用工具
rfkillsudo apt install rfkill
检查无线网卡状态:
rfkill list 检查网卡设备是否被blockrfkill list
如果看到无线网卡状态是 Soft blocked 则表明软件关闭了无线网卡:
rfkill list 输出中有 blocked 状态设备则表明被关闭0: phy0: Wireless LAN
Soft blocked: yes
Hard blocked: no
则使用以下命令启用无线(unblock):
rfkill unblock 恢复rfkill unblock wifi
如果使用桌面版本Ubuntu,默认是启用了NetworkManager,则会和手工设置
wpa_supplicant冲突,所以需要停止NetworkManager:sudo systemctl stop NetworkManager sudo systemctl disable NetworkManager
如果使用服务器版本Ubuntu,默认是启用了netplan,也会和手工设置
wpa_supplicant冲突
确定无线网卡
使用
iwconfig找出无线网卡名字:iwconfig
通常无线网卡名字是 wlan0 ,但是也可能看到常见的 wlp3s0 。
如果无线网卡接口是down状态,可以使用
ifconfig命令启用:sudo ifconfig wlp3s0 up
然后扫描周边无线网络:
sudo iwlist wlp3s0 scan | grep ESSID
使用wpa_supplicant连接无线
安装
wpa_supplicantsudo apt install wpa_supplicant
创建初始配置:
wpa_passphrase 初始化一个简单配置wpa_passphrase your-ESSID your-passphrase | sudo tee /etc/wpa_supplicant/wpa_supplicant.conf
sudo chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf
备注
对于5G网络连接需要增加 country code 配置(类似于 netplan网络配置 的 REGDOMAIN=CN ):
wpa_supplicant.conf 增加 country=CN 来连接5G WIFIcountry=CN
使用以下命令连接无线:
wpa_supplicant 验证配置(前台执行)sudo wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlp3s0
注意,这时是前台运行 wpa_supplicant ,当连接建立以后,请另外开一个终端窗口,执行 iwconfig 命令检查无线是否连接正常,应该看到 wlps3s0 连接到指定的AP。
按下
CTRL+C终止前台运行的wpa_supplicant进程,然后加上-B参数让它后台运行:
wpa_supplicant 的 -B 参数后台运行sudo wpa_supplicant -B -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlp3s0
当完成无线连接之后,我们需要获取DHCP地址,所以我们还要运行
dhclient:
wpa_supplicant 完成验证运行后,启动 dhclient 获取动态IPsudo dhclient wlp3s0
如果一切正常,使用 ifconfig wlp3s0 将看到无线网卡获得IP地址并能够正常上网。
802.1x和EAP
IEEE8021X是用于有线网络的认证,对应的无线网络认证是WPA-EAP,所以在配置 wpa_supplicant-wired.conf 使用如下配置:
ctrl_interface=/run/wpa_supplicant
ap_scan=0
network={
key_mgmt=IEEE8021X
eap=PEAP
identity="user_name"
password="user_password"
phase2="autheap=MSCHAPV2"
}
而无线网络则替换 IEEE8021X 成 WPA-EAP 并且移除 ap_scan=0 :
/etc/wpa_supplicant/wpa_supplicant.conf 配置 WPA-EAP (对应有线网络的 IEEE8021X )ctrl_interface=/var/run/wpa_supplicant
# 配置Country Code支持5G Hz无线连接
country=CN
# ap_scan支持扫描隐藏的SSID
ap_scan=1
network={
ssid="SSID-OFFICE"
key_mgmt=WPA-EAP
eap=PEAP
phase1="peaplabel=0"
phase2="auth=MSCHAPV2"
identity="user_name"
password="user_password"
priority=10
}
简单的wpa_supplicant脚本
一个非常简单的wpa_supplicant脚本,结合前面配置文件启动并连接无线:
1sudo ifconfig wlp3s0 down
2sleep 1
3sudo ifconfig wlp3s0 up
4sudo wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant-office.conf -i wlp3s0 &
5sleep 5
6sudo dhcpcd wlp3s0
连接隐藏的无线网络
有些无线网络SSID并不广播,所以需要在 /etc/wpa_supplicant.conf 配置中添加(注意,是添加在每一段 network 配置中):
scan_ssid=1
5G Hz无线网络国家代码
如果使用了5G Hz无线AP,一定要在配置中添加 country=CN 或者对应国家Code,否则会导致 wpa_supplicant 运行时错误连接 bssid=00:00:00:00:00:00 的AP,日志显示类似:
Nov 05 16:18:51 pi-worker2 wpa_supplicant[1932]: wlan0: CTRL-EVENT-ASSOC-REJECT bssid=00:00:00:00:00:00 status_code=16
Nov 05 16:10:27 pi-worker2 wpa_supplicant[1849]: wlan0: Trying to associate with SSID 'SSID-OFFICE'
Nov 05 16:10:30 pi-worker2 wpa_supplicant[1849]: wlan0: CTRL-EVENT-ASSOC-REJECT bssid=00:00:00:00:00:00 status_code=16
Nov 05 16:10:30 pi-worker2 wpa_supplicant[1849]: wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=0 ssid="SSID-OFFICE" auth_failures=1 duration=23 reason=CONN_FAILED
这是因为5GHz是一个受控频率,需要根据不同国家进行调整country code,否则无法连接。
备注
我曾经在 树莓派Ubuntu网络设置 反复折腾了一周时间 排查wpa_supplicant无法连接5GHz无线问题 。
如果使用 netplan网络配置 配置管理 systemd-networkd ,则同样设置 REGDOMAIN=CN 。
NetworkManager 和 wpa_supplicant
NetworkManager 是通过 D-Bus 和 wpa_supplicant 通讯的,我在 Raspbery Pi OS(Raspbian) 上实践( 树莓派Raspberry Pi 5 )发现,当通过 raspi-config 配置无线网络,实际上生成的是 /etc/NetworkManager/system-connections/MY_SSID.nmconnection (这里假设连接的是 MY_SSID 这个无线AP) :
raspi-config 生成 NetworkManager 无线配置[connection]
id=MY_SSID
uuid=xxxx-xxxx-xxxx-xxxx
type=wifi
interface-name=wlan0
[wifi]
mode=infrastructure
ssid=MY_SSID
[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=MY_PSK
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
[proxy]
此时对应的 /etc/wpa_supplicant/wpa_supplicant.conf 非常简单:
/etc/wpa_supplicant/wpa_supplicant.confctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
#update_config=1
#修改成0表示不允许更新配置,因为NetworkManager无需修改这个配置文件
update_config=0
注意, NetworkManager 不会管理 /etc/network/interfaces 配置中列出的接口,所以需要确保这个配置文件中没有包含无线网卡,以便让渡给NetworkManager管理
NetworkManager 和 wpa_supplicant 的无线连接优先级设置
当配置多个无线网络时候,可以设置一个优先级( priority )来按一定顺序连接无线, NetworkManager 和 wpa_supplicant 都支持传递这个配置参数,但略有不同:
直接编辑
/etc/wpa_supplicant/wpa_supplicant.conf,可以为每个network配置不同的priority(数字越小优先级越低):
/etc/wpa_supplicant/wpa_supplicant.conf 配置 WPA-EAP (对应有线网络的 IEEE8021X )ctrl_interface=/var/run/wpa_supplicant
# 配置Country Code支持5G Hz无线连接
country=CN
# ap_scan支持扫描隐藏的SSID
ap_scan=1
network={
ssid="SSID-OFFICE"
key_mgmt=WPA-EAP
eap=PEAP
phase1="peaplabel=0"
phase2="auth=MSCHAPV2"
identity="user_name"
password="user_password"
priority=10
}
如果通过 NetworkManager 来管理无线网络,则在使用
nmcli命令时就可以指定priority:
nmcli con add con-name home ifname wlp3s0 type wifi ssid home \
wifi-sec.key-mgmt wpa-psk wifi-sec.psk MYPASSWORD
connection.autoconnect-priority 10
上述 nmcli 命令传递参数会在 /etc/NetworkManager/system-connections/home.nmconnection 配置文件的 [connection] 配置段添加 autoconnect-priority=10
连接没有密码保护的开放网络
对于在机场等公共空间,开放无密码的wifi,可以设置
wpa_supplicant.conf的network段落key_mgmt=NONE:
network={
ssid="public wifi"
key_mgmt=NONE
priority=-999
}
如果上述配置中没有指定 ssid 则会连接无线范围内任意一个开放网络
启动时自动运行
警告
这段配置 systemd 方法虽然可行,但是现在已经没有必要直接修改 wpa_supplicant.service 配置文件了。标准的方法是通过激活 wpa_supplicant@interfice.service 来让服务读取对应的 /etc/wpa_supplicant/wpa_supplicant-interface.conf 。例如,对于 wlan0 ,应该执行:
systemctl enable wpa_supplicant@wlan0.service
为了能在操作系统启动时自动连接无线网络,我们需要编辑 wpa_supplicant.service 配置:
sudo cp /lib/systemd/system/wpa_supplicant.service /etc/systemd/system/wpa_supplicant.service
然后编辑 /etc/systemd/system/wpa_supplicant.service ,将以下配置:
ExecStart=/sbin/wpa_supplicant -u -s -O /run/wpa_supplicant
修改成:
ExecStart=/sbin/wpa_supplicant -u -s -c /etc/wpa_supplicant.conf -i wlp3s0
如果在 wpa_supplicant.service 配置中有如下内容:
Alias=dbus-fi.w1.wpa_supplicant1.service
则注释掉(添加 # ):
#Alias=dbus-fi.w1.wpa_supplicant1.service
现在我们可以激活 wpa_supplicant.service
sudo systemctl enable wpa_supplicant.service
我们也需要启动 dhclient 来获得IP,所以创建 /etc/systemd/system/dhclient.service 内容如下:
[Unit]
Description= DHCP Client
Before=network.target
[Service]
Type=simple
ExecStart=/sbin/dhclient wlp3s0 -v
ExecStop=/sbin/dhclient wlp3s0 -r
[Install]
WantedBy=multi-user.target
然后激活服务:
sudo systemctl enable dhclient.service
获得静态IP地址
DHCP客户端也可以向服务器请求分配固定的IP地址,编辑 /etc/dhcp/dhclient.conf 添加以下行内容:
interface "wlp3s0" {
send dhcp-requested-address 192.168.0.122;
}
然后重启dhclient服务:
sudo systemctl restart dhclient
使用主机名访问Ubuntu服务
实际上不需要分配静态IP地址就能够对外提供服务。Ubuntu可以使用 mDNS (Multicast DNS) 来向局域网公告自己的主机名,这样客户端就可以通过主机名来访问这台服务器上的服务。这样主机名可以解析到IP地址,即使你的主机IP地址变化。
要使用mDNS,需要安装 avahi-daemon ,这时一个实现 mDNS/DNS-SD 的开源实现:
sudo apt install avahi-daemon
启动服务:
sudo systemctl start avahi-daemon
激活启动服务:
sudo systemctl enable avahi-daemon
avahi-daemon监听在UDP端口5353,所以防火墙需要打开这个端口。如果你使用UFW,则运行以下命令:
sudo ufw allow 5353/udp
现在你需要设置服务器的唯一主机名,使用 hostnamectl 命令:
sudo hostnamectl set-hostname ubuntubox
注意,此时新设置的 ubuntubox 还不能被其他局域网主机看到,我们需要重启 avahi-daemon
sudo systemclt restart avahi-daemon
检查 avahi-daemon 状态:
systemctl status avahi-daemon
备注
需要注意,mDNS主机名以 .local 结尾,所以上述设置主机名 ubuntubox 在mDNS中显示的名字是 ubuntubox.local
对于要使用avahi的客户端,需要安装 mDNS/DNS-SD 软件:
Linux需要安装
avahi-daemonWindows需要激活
Bonjour服务,也就是安装 Bonjour print service 或者直接安装 iTunesmacOS不需要安装任何软件,默认已经激活了Bonjour