macOS根据连接的WiFi自动切换代理

问题描述

macOS下的代理不像iOS那样设置在每个WiFi连接中的,而是不同WiFi使用同一个设置。 这在多个网络环境下需要不同的代理设置时就很不方便了。

搜索

修改代理配置

可以使用networksetup,找到两种方式:

  • 使用networksetup命令,直接设置代理和开关代理;
  • 使用networksetup命令,修改网络位置,每个网络位置可以设置不同的代理和其他一些内容,从而达到修改代理配置的目的。

自动触发

不依赖第三方软件可以使用launchd

networksetup

设置代理

networksetup -setwebproxy "Wi-Fi" 192.168.2.2 8118
networksetup -setsecurewebproxy "Wi-Fi" 192.168.2.2 8118
networksetup -setwebproxystate "Wi-Fi" on
networksetup -setsecurewebproxystate "Wi-Fi" on

关闭代理

networksetup -setwebproxystate "Wi-Fi" off
networksetup -setsecurewebproxystate "Wi-Fi" off

切换网络位置

networksetup -switchtolocation "Automatic"

如果新建了叫做Home的网络位置,可以使用

networksetup -switchtolocation "Home"

切换到Home网络位置。

获取WiFi网络SSID

ipconfig

对于Sequoia(15),好几个获取SSID的方式都失效了,最后找到通过ipconfig可以。

ipconfig getsummary $(networksetup -listallhardwareports | awk '/Hardware Port: Wi-Fi/{getline; print $2}') | awk -F ' SSID : ' '/ SSID : / {print $2}'

airport

对于Monterey(12)到Sonoma(14.3.1),可以使用

/System/Library/PrisvateFrameworks/Apple80211.framework/Resources/airport -I | awk -F': ' '/ SSID: / {print $2}'

wdutil

对于Sonoma(14.4),可以使用

sudo /usr/bin/wdutil info | /usr/bin/awk '/SSID/ { print $NF }' | head -n 1

缺点是需要sudo

networksetup

对于Monterey(12)到Sonoma(14.4)的版本,可以使用

networksetup -getairportnetwork en0 | /usr/bin/awk -F ": " '{ print $2 }'

优点是兼容版本最广泛

shell脚本

直接切换代理的完整脚本/usr/local/bin/proxy_switch.sh

#!/bin/sh
SSID=$(/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | awk -F': ' '/ SSID: / {print $2}')
# Wi-Fi 名称替换为实际值,例如 "MY-WIFI-HOME"
if [ "$SSID" = "MY-WIFI-HOME" ]; then
    # 启用代理(替换代理地址和端口)
    networksetup -setwebproxy "Wi-Fi" 192.168.2.2 8118
    networksetup -setsecurewebproxy "Wi-Fi" 192.168.2.2 8118
    networksetup -setwebproxystate "Wi-Fi" on
    networksetup -setsecurewebproxystate "Wi-Fi" on
else
    # 关闭代理
    networksetup -setwebproxystate "Wi-Fi" off
    networksetup -setsecurewebproxystate "Wi-Fi" off
fi

记得给文件设置可执行属性,chmod +x /usr/local/bin/proxy_switch.sh

假如创建了Home和Work两个网络位置,完整的脚本/usr/local/bin/wifi-trigger-location.sh如下

#!/bin/bash
#sleep 0.2 # 这边可以考虑加上延迟,防止获取不到SSID
current_ssid=`ipconfig getsummary $(networksetup -listallhardwareports | awk '/Hardware Port: Wi-Fi/{getline; print $2}') | awk -F ' SSID : ' '/ SSID : / {print $2}'`
current_location=$(networksetup -getcurrentlocation)
# 根据 Wi-Fi 名称切换网络位置
if [[ "$current_ssid" == "MY-WIFI-HOME" ]]; then
    new_location="Home"
elif [[ "$current_ssid" == "MY-WIFI-WORK" ]]; then
    new_location="Work"
else
    new_location="Automatic"
fi

if [[ "$current_location" != "$new_location" ]]; then
    networksetup -switchtolocation "$new_location" >> ~/wifitrigger.log
    echo "switching to $new_location" >> ~/wifitrigger.log
else
    echo "already $new_location" >> ~/wifitrigger.log
fi

记得给文件设置可执行属性,chmod +x /usr/local/bin/wifi-trigger-location.sh

连接WiFi时触发

launchd

macOS的launched类似于Linux的systemd,可以用来定时或条件触发执行命令。 编写一个~/Library/LaunchAgents/com.user.wifitrigger.plist文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.wifitrigger</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/wifi-trigger-location.sh</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <!-- 监听网络配置变化 -->
        <string>/Library/Preferences/SystemConfiguration/com.apple.wifi.message-tracer.plist</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

通过launchctl load -w ~/Library/LaunchAgents/com.user.wifitrigger.plist加载配置文件。 通过launchctl unload ~/Library/LaunchAgents/com.user.wifitrigger.plist卸载配置文件。

此时WiFi连接时就会触发/usr/local/bin/wifi-trigger-location.sh脚本。


最后修改于 2025-02-23