Skip to content

Instantly share code, notes, and snippets.

@pd12bb
Last active January 11, 2022 08:39
Show Gist options
  • Select an option

  • Save pd12bb/2139b806be27d4f422c6885c16920b9e to your computer and use it in GitHub Desktop.

Select an option

Save pd12bb/2139b806be27d4f422c6885c16920b9e to your computer and use it in GitHub Desktop.
auto edit endpoint of wg peers (dns)
#!/bin/bash
debug=0
configDir='/etc/wireguard/' # 配置文件夹 /etc/wireguard/
interfaces=('wg0' 'wg1') # 需要动态的接口
timeout='180' # 超时时间,以秒记
url='https://dns.alidns.com/resolve' # doh URL
fontRed='\033[31m'
fontGreen='\033[32m'
fontBlue='\033[36m'
fontNormal='\033[0m'
function echoRed() {
echo -e "${fontRed}${*}${fontNormal}"
}
function echoBlue() {
echo -e "${fontBlue}${*}${fontNormal}"
}
function echoGreen() {
echo -e "${fontGreen}${*}${fontNormal}"
}
function debug() {
if [ "$debug" == "1" ]; then
echo "$*"
fi
}
function doh() { # 输入 name type 返回结果
debug "查询dns api ..." 1>&2
case "$2" in
A)
type=1
;;
NS)
type=2
;;
CNAME)
type=5
;;
SOA)
type=6
;;
TXT)
type=16
;;
AAAA)
type=28
;;
*)
type=1
;;
esac
curlInfo=$(curl -s --retry 3 --max-time 60 "${url}?name=${1}&type=${type}")
if [[ "$?" -ne "0" ]]; then
echoRed "curl Error !" 1>&2
return 1
fi
dnsAnswer=$(echo "${curlInfo}" | grep "\"Answer\":")
if [[ -z "${dnsAnswer}" ]]; then
echoRed "Record type $2 not found !" 1>&2
return 1
else
echo "${dnsAnswer}" | sed -e "s/.*\"Answer\":\[{//g" -e "s/},{/\n/g" -e "s/}.*$//g" | tr ',' '\n' | grep '\"data\"' | sed -e 's/\"$//g' -e 's/.*\"//g' | head -1
return 0
fi
}
for interface in "${interfaces[@]}" ; do
echoGreen "Searching ${interface} ..."
wg show ${interface} > /dev/null 2>&1
if [[ "$?" -ne '0' ]]; then
echoRed "Interface ${interface} not exist !"
continue
fi
debug "查询 ${interface} Peers ..."
peers=($(wg show ${interface} persistent-keepalive | grep -v 'off' | awk '{printf($1 " ")}'))
if [[ -z "${peers[@]}" ]]; then
debug "找不到需要更新的peer"
continue
fi
if [[ ! -r "${configDir}/${interface}.conf" ]]; then # 确认配置文件可读
echoRed "Config file unreadable !"
continue
fi
config=$(cat "${configDir}/${interface}.conf") # 获取配置文件
for peer in "${peers[@]}"; do
threshold=$(date +%s --date="${timeout} seconds ago")
debug "上次握手最小值为 ${threshold}"
echoGreen "Searching Peer ${peer} ..."
latestHandshakes=$(wg show ${interface} latest-handshakes | grep "${peer}" | head -1 | awk '{printf($2)}')
debug "Peer ${peer} 上次握手时间 ${latestHandshakes}"
if [[ "${latestHandshakes}" -lt "${threshold}" ]]; then
echoRed "Interface ${interface} Peer ${peer} timeout"
endPoint=$(echo "${config}" | sed -e 's/#.*//g' -e 's/[[:blank:]]//g' | tr '\n' ' ' | sed -e 's/\[Peer\]/\n/g' | grep "PublicKey=${peer}" | tr ' ' '\n' | grep "Endpoint" | cut -d '=' -f 2)
debug "Interface ${interface} Peer ${peer} Endpoint ${endPoint}"
if [[ -z ${endPoint} ]]; then
echoRed "Interface ${interface} Peer ${peer} Endpoint not found !"
continue
fi
domain=$(echo "${endPoint}" | cut -d ':' -f 1)
port=$(echo "${endPoint}" | cut -d ':' -f 2)
address=$(doh "${domain}" "AAAA") # 优先ipv6
if [[ "$?" -ne '0' ]]; then
address=$(doh "${domain}" "A")
fi
debug "域名解析地址为 ${address}"
procEndPoint=$(wg show ${interface} endpoints | grep "${peer}" | head -1 | awk '{printf($2)}')
if [[ "$procEndPoint" == "${address}:${port}" || "$procEndPoint" == "[${address}]:${port}" ]]; then
echoGreen "Address unchange !"
continue
fi
echoGreen "Address change !"
wg set ${interface} peer ${peer} endpoint "[${address}]:${port}"
fi
done
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment