api.sh 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #!/usr/bin/env bash
  2. # 只允许root运行
  3. [[ "$EUID" -ne '0' ]] && echo "Error:This script must be run as root!" && exit 1;
  4. # 帮助
  5. help() {
  6. echo -ne " Usage:\n\tbash api.sh\t-h/--help\t\thelp\n\t\t\t-f/--file string\tConfiguration file (default "warp-account.conf")\n\t\t\t-r/--registe\t\tRegiste an account\n\t\t\t-t/--token\t\tRegiste with a team token\n\t\t\t-d/--device\t\tGet the devices information and plus traffic quota\n\t\t\t-a/--app\t\tFetch App information\n\t\t\t-b/--bind\t\tGet the account blinding devices\n\t\t\t-n/--name\t\tChange the device name\n\t\t\t-l/--license\t\tChange the license\n\t\t\t-u/--unbind\t\tUnbine a device from the account\n\t\t\t-c/--cancle\t\tCancle the account\n\t\t\t-i/--id\t\t\tShow the client id and reserved\n\n"
  7. }
  8. # 获取账户信息
  9. fetch_account_information() {
  10. # 如不使用账户信息文件,则手动填写 Device id 和 Api token
  11. if [ -s "$registe_path" ]; then
  12. # 官方 api 文件
  13. if grep -q 'client_id' $registe_path; then
  14. id=$(grep -m1 '"id' "$registe_path" | cut -d\" -f4)
  15. token=$(grep '"token' "$registe_path" | cut -d\" -f4)
  16. client_id=$(grep 'client_id' "$registe_path" | cut -d\" -f4)
  17. # client 文件,默认存放路径为 /var/lib/cloudflare-warp/reg.json
  18. elif grep -q 'registration_id' $registe_path; then
  19. id=$(cut -d\" -f4 "$registe_path")
  20. token=$(cut -d\" -f8 "$registe_path")
  21. # wgcf 文件,默认存放路径为 /etc/wireguard/wgcf-account.toml
  22. elif grep -q 'access_token' $registe_path; then
  23. id=$(grep 'device_id' "$registe_path" | cut -d\' -f2)
  24. token=$(grep 'access_token' "$registe_path" | cut -d\' -f2)
  25. # warp-go 文件,默认存放路径为 /opt/warp-go/warp.conf
  26. elif grep -q 'PrivateKey' $registe_path; then
  27. id=$(awk -F' *= *' '/^Device/{print $2}' "$registe_path")
  28. token=$(awk -F' *= *' '/^Token/{print $2}' "$registe_path")
  29. else
  30. echo " There is no registered account information, please check the content. " && exit 1
  31. fi
  32. else
  33. read -rp " Input device id: " id
  34. local i=5
  35. until [[ "$id" =~ ^(t\.)?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}$ ]]; do
  36. (( i-- )) || true
  37. [ "$i" = 0 ] && echo " Input errors up to 5 times. The script is aborted. " && exit 1 || read -rp " Device id should be 36 or 38 characters, please re-enter (${i} times remaining): " id
  38. done
  39. read -rp " Input api token: " token
  40. local i=5
  41. until [[ "$token" =~ ^[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}$ ]]; do
  42. (( i-- )) || true
  43. [ "$i" = 0 ] && echo " Input errors up to 5 times. The script is aborted. " && exit 1 || read -rp " Api token should be 36 characters, please re-enter (${i} times remaining): " token
  44. done
  45. fi
  46. }
  47. # 注册warp账户
  48. registe_account() {
  49. # 生成 wireguard 公私钥,并且补上 private key
  50. if [ $(type -p wg) ]; then
  51. private_key=$(wg genkey)
  52. public_key=$(wg pubkey <<< "$private_key")
  53. else
  54. wg_api=$(curl -sSL https://wg.cloudflare.now.cc)
  55. private_key=$(echo "$wg_api" | awk 'NR==2 {print $2}')
  56. public_key=$(echo "$wg_api" | awk 'NR==1 {print $2}')
  57. fi
  58. registe_path=${registe_path:-warp-account.conf}
  59. [[ "$(dirname "$registe_path")" != '.' ]] && mkdir -p $(dirname "$registe_path")
  60. install_id=$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 22)
  61. fcm_token="${install_id}:APA91b$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 134)"
  62. curl --request POST 'https://api.cloudflareclient.com/v0a2158/reg' \
  63. --silent \
  64. --location \
  65. --tlsv1.3 \
  66. --header 'User-Agent: okhttp/3.12.1' \
  67. --header 'CF-Client-Version: a-6.10-2158' \
  68. --header 'Content-Type: application/json' \
  69. --header "Cf-Access-Jwt-Assertion: ${team_token}" \
  70. --data '{"key":"'${public_key}'","install_id":"'${install_id}'","fcm_token":"'${fcm_token}'","tos":"'$(date +"%Y-%m-%dT%H:%M:%S.000Z")'","model":"PC","serial_number":"'${install_id}'","locale":"zh_CN"}' \
  71. | python3 -m json.tool | sed "/\"account_type\"/i\ \"private_key\": \"$private_key\"," > $registe_path
  72. [[ ! -s $registe_path || $(grep 'error' $registe_path) ]] && { rm -f $registe_path; exit 1; } || { cat $registe_path; exit 0; }
  73. }
  74. # 获取设备信息
  75. device_information() {
  76. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  77. curl --request GET "https://api.cloudflareclient.com/v0a2158/reg/${id}" \
  78. --silent \
  79. --location \
  80. --header 'User-Agent: okhttp/3.12.1' \
  81. --header 'CF-Client-Version: a-6.10-2158' \
  82. --header 'Content-Type: application/json' \
  83. --header "Authorization: Bearer ${token}" \
  84. | python3 -m json.tool
  85. }
  86. # 获取账户APP信息
  87. app_information() {
  88. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  89. curl --request GET "https://api.cloudflareclient.com/v0a2158/client_config" \
  90. --silent \
  91. --location \
  92. --header 'User-Agent: okhttp/3.12.1' \
  93. --header 'CF-Client-Version: a-6.10-2158' \
  94. --header 'Content-Type: application/json' \
  95. --header "Authorization: Bearer ${token}" \
  96. | python3 -m json.tool
  97. }
  98. # 查看账户绑定设备
  99. account_binding_devices() {
  100. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  101. curl --request GET "https://api.cloudflareclient.com/v0a2158/reg/${id}/account/devices" \
  102. --silent \
  103. --location \
  104. --header 'User-Agent: okhttp/3.12.1' \
  105. --header 'CF-Client-Version: a-6.10-2158' \
  106. --header 'Content-Type: application/json' \
  107. --header "Authorization: Bearer ${token}" \
  108. | python3 -m json.tool
  109. }
  110. # 添加或者更改设备名
  111. change_device_name() {
  112. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  113. curl --request PATCH "https://api.cloudflareclient.com/v0a2158/reg/${id}/account/reg/${id}" \
  114. --silent \
  115. --location \
  116. --header 'User-Agent: okhttp/3.12.1' \
  117. --header 'CF-Client-Version: a-6.10-2158' \
  118. --header 'Content-Type: application/json' \
  119. --header "Authorization: Bearer ${token}" \
  120. --data '{"name":"'$device_name'"}' \
  121. | python3 -m json.tool
  122. }
  123. # 更换 license
  124. change_license() {
  125. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  126. curl --request PUT "https://api.cloudflareclient.com/v0a2158/reg/${id}/account" \
  127. --silent \
  128. --location \
  129. --header 'User-Agent: okhttp/3.12.1' \
  130. --header 'CF-Client-Version: a-6.10-2158' \
  131. --header 'Content-Type: application/json' \
  132. --header "Authorization: Bearer ${token}" \
  133. --data '{"license": "'$license'"}' \
  134. | python3 -m json.tool
  135. }
  136. # 删除绑定设备
  137. unbind_devide() {
  138. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  139. curl --request PATCH "https://api.cloudflareclient.com/v0a2158/reg/${id}/account/reg/${id}" \
  140. --silent \
  141. --location \
  142. --header 'User-Agent: okhttp/3.12.1' \
  143. --header 'CF-Client-Version: a-6.10-2158' \
  144. --header 'Content-Type: application/json' \
  145. --header "Authorization: Bearer ${token}" \
  146. --data '{"active":false}' \
  147. | python3 -m json.tool
  148. }
  149. # 删除账户
  150. cancle_account() {
  151. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  152. local result=$(curl --request DELETE "https://api.cloudflareclient.com/v0a2158/reg/${id}" \
  153. --silent \
  154. --location \
  155. --header 'User-Agent: okhttp/3.12.1' \
  156. --header 'CF-Client-Version: a-6.10-2158' \
  157. --header 'Content-Type: application/json' \
  158. --header "Authorization: Bearer ${token}")
  159. [ -z "$result" ] && echo " Success. The account has been cancelled. " || echo " Failure. The account is not available. "
  160. }
  161. # reserved 解码
  162. decode_reserved() {
  163. [[ -z "$id" && -z "$token" ]] && fetch_account_information
  164. [ -z "$client_id" ] && { fetch_client_id=$(device_information); client_id=$(expr " $fetch_client_id" | awk -F'"' '/client_id/{print $4}'); }
  165. reserved=$(echo "$client_id" | base64 -d | xxd -p | fold -w2 | while read HEX; do printf '%d ' "0x${HEX}"; done | awk '{print "["$1", "$2", "$3"]"}')
  166. echo -e "client id: $client_id\nreserved : $reserved"
  167. }
  168. [[ "$#" -eq '0' ]] && help && exit;
  169. while [[ $# -ge 1 ]]; do
  170. case $1 in
  171. -f|--file)
  172. shift
  173. registe_path="$1"
  174. shift
  175. ;;
  176. -r|--registe)
  177. run=registe_account
  178. shift
  179. ;;
  180. -d|--device)
  181. run=device_information
  182. shift
  183. ;;
  184. -a|--app)
  185. run=app_information
  186. shift
  187. ;;
  188. -b|--bind)
  189. run=account_binding_devices
  190. shift
  191. ;;
  192. -n|--name)
  193. shift
  194. device_name="$1"
  195. run=change_device_name
  196. shift
  197. ;;
  198. -l|--license)
  199. shift
  200. license="$1"
  201. run=change_license
  202. shift
  203. ;;
  204. -u|--unbind)
  205. run=unbind_devide
  206. shift
  207. ;;
  208. -c|--cancle)
  209. run=cancle_account
  210. shift
  211. ;;
  212. -i|--id)
  213. run=decode_reserved
  214. shift
  215. ;;
  216. -t|--token)
  217. shift
  218. team_token="$1"
  219. shift
  220. ;;
  221. -h|--help)
  222. help
  223. exit
  224. ;;
  225. *)
  226. help
  227. exit
  228. ;;
  229. esac
  230. done
  231. # 根据参数运行
  232. $run