wireguard.sh 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. #!/usr/bin/env bash
  2. #
  3. # This is a Shell script for configure and start WireGuard VPN server.
  4. #
  5. # Copyright (C) 2019 - 2024 Teddysun <[email protected]>
  6. #
  7. # Reference URL:
  8. # https://www.wireguard.com
  9. # https://git.zx2c4.com/WireGuard
  10. # https://teddysun.com/554.html
  11. trap _exit INT QUIT TERM
  12. cur_dir="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"
  13. [ ${EUID} -ne 0 ] && _red "This script must be run as root\n" && exit 1
  14. _red() {
  15. printf '\033[1;31;31m%b\033[0m' "$1"
  16. }
  17. _green() {
  18. printf '\033[1;31;32m%b\033[0m' "$1"
  19. }
  20. _yellow() {
  21. printf '\033[1;31;33m%b\033[0m' "$1"
  22. }
  23. _printargs() {
  24. printf -- "%s" "[$(date)] "
  25. printf -- "%s" "$1"
  26. printf "\n"
  27. }
  28. _info() {
  29. _printargs "$@"
  30. }
  31. _warn() {
  32. printf -- "%s" "[$(date)] "
  33. _yellow "$1"
  34. printf "\n"
  35. }
  36. _error() {
  37. printf -- "%s" "[$(date)] "
  38. _red "$1"
  39. printf "\n"
  40. exit 2
  41. }
  42. _exit() {
  43. printf "\n"
  44. _red "$0 has been terminated."
  45. printf "\n"
  46. exit 1
  47. }
  48. _exists() {
  49. local cmd="$1"
  50. if eval type type > /dev/null 2>&1; then
  51. eval type "$cmd" > /dev/null 2>&1
  52. elif command > /dev/null 2>&1; then
  53. command -v "$cmd" > /dev/null 2>&1
  54. else
  55. which "$cmd" > /dev/null 2>&1
  56. fi
  57. local rt=$?
  58. return ${rt}
  59. }
  60. _ipv4() {
  61. local ipv4="$( ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \
  62. grep -E -v "^192\.168|^172\.1[6-9]\.|^172\.2[0-9]\.|^172\.3[0-2]\.|^10\.|^127\.|^255\.|^0\.|^169\.254\." | head -n 1 )"
  63. [ -z "${ipv4}" ] && ipv4="$( wget -qO- -t1 -T2 http://ipv4.icanhazip.com )"
  64. [ -z "${ipv4}" ] && ipv4="$( wget -qO- -t1 -T2 http://ipinfo.io/ip )"
  65. printf -- "%s" "${ipv4}"
  66. }
  67. _ipv6() {
  68. local ipv6=""
  69. ipv6="$(wget -qO- -t1 -T2 http://ipv6.icanhazip.com)"
  70. printf -- "%s" "${ipv6}"
  71. }
  72. _nic() {
  73. local nic=""
  74. nic="$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)"
  75. printf -- "%s" "${nic}"
  76. }
  77. _port() {
  78. local port="$(shuf -i 1024-20480 -n 1)"
  79. while true; do
  80. if _exists "netstat" && netstat -tunlp | grep -w "${port}" > /dev/null 2>&1; then
  81. port="$(shuf -i 1024-20480 -n 1)"
  82. else
  83. break
  84. fi
  85. done
  86. printf -- "%s" "${port}"
  87. }
  88. _os() {
  89. local os=""
  90. [ -f "/etc/debian_version" ] && source /etc/os-release && os="${ID}" && printf -- "%s" "${os}" && return
  91. [ -f "/etc/fedora-release" ] && os="fedora" && printf -- "%s" "${os}" && return
  92. [ -f "/etc/redhat-release" ] && os="centos" && printf -- "%s" "${os}" && return
  93. }
  94. _os_full() {
  95. [ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return
  96. [ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
  97. [ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return
  98. }
  99. _os_ver() {
  100. local main_ver="$( echo $(_os_full) | grep -oE "[0-9.]+")"
  101. printf -- "%s" "${main_ver%%.*}"
  102. }
  103. _error_detect() {
  104. local cmd="$1"
  105. _info "${cmd}"
  106. eval ${cmd} 1> /dev/null
  107. if [ $? -ne 0 ]; then
  108. _error "Execution command (${cmd}) failed, please check it and try again."
  109. fi
  110. }
  111. _version_gt(){
  112. test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"
  113. }
  114. _version_ge(){
  115. test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"
  116. }
  117. _is_installed() {
  118. install_flag=(0 0)
  119. if _exists "wg" && _exists "wg-quick"; then
  120. install_flag[0]=1
  121. fi
  122. if [ -s "/lib/modules/$(uname -r)/extra/wireguard.ko" ] \
  123. || [ -s "/lib/modules/$(uname -r)/extra/wireguard.ko.xz" ] \
  124. || [ -s "/lib/modules/$(uname -r)/updates/dkms/wireguard.ko" ] \
  125. || [ -s "/lib/modules/$(uname -r)/updates/dkms/wireguard.ko.xz" ] \
  126. || [ -s "/lib/modules/$(uname -r)/kernel/wireguard/wireguard.ko" ] \
  127. || [ -s "/lib/modules/$(uname -r)/kernel/drivers/net/wireguard/wireguard.ko" ] \
  128. || [ -s "/lib/modules/$(uname -r)/kernel/drivers/net/wireguard/wireguard.ko.xz" ]; then
  129. install_flag[1]=1
  130. fi
  131. if [ "${install_flag[0]}" = "1" ] && [ "${install_flag[1]}" = "1" ]; then
  132. return 0
  133. fi
  134. if [ "${install_flag[0]}" = "1" ] && [ "${install_flag[1]}" = "0" ]; then
  135. return 1
  136. fi
  137. if [ "${install_flag[0]}" = "0" ] && [ "${install_flag[1]}" = "1" ]; then
  138. return 2
  139. fi
  140. if [ "${install_flag[0]}" = "0" ] && [ "${install_flag[1]}" = "0" ]; then
  141. return 3
  142. fi
  143. }
  144. get_latest_module_ver() {
  145. wireguard_ver="$(wget --no-check-certificate -qO- https://api.github.com/repos/WireGuard/wireguard-linux-compat/tags | grep 'name' | head -1 | cut -d\" -f4)"
  146. if [ -z "${wireguard_ver}" ]; then
  147. wireguard_ver="$(curl -Lso- https://api.github.com/repos/WireGuard/wireguard-linux-compat/tags | grep 'name' | head -1 | cut -d\" -f4)"
  148. fi
  149. if [ -z "${wireguard_ver}" ]; then
  150. _error "Failed to get latest wireguard module version from github"
  151. fi
  152. }
  153. get_latest_tools_ver() {
  154. wireguard_tools_ver="$(wget --no-check-certificate -qO- https://api.github.com/repos/WireGuard/wireguard-tools/tags | grep 'name' | head -1 | cut -d\" -f4)"
  155. if [ -z "${wireguard_tools_ver}" ]; then
  156. wireguard_tools_ver="$(curl -Lso- https://api.github.com/repos/WireGuard/wireguard-tools/tags | grep 'name' | head -1 | cut -d\" -f4)"
  157. fi
  158. if [ -z "${wireguard_tools_ver}" ]; then
  159. _error "Failed to get latest wireguard tools version from github"
  160. fi
  161. }
  162. # Check OS version
  163. check_os() {
  164. _info "Check OS version"
  165. if _exists "virt-what"; then
  166. virt="$(virt-what)"
  167. elif _exists "systemd-detect-virt"; then
  168. virt="$(systemd-detect-virt)"
  169. fi
  170. if [ -n "${virt}" -a "${virt}" = "lxc" ]; then
  171. _error "Virtualization is LXC, which is not supported."
  172. fi
  173. if [ -n "${virt}" -a "${virt}" = "openvz" ] || [ -d "/proc/vz" ]; then
  174. _error "Virtualization is OpenVZ, which is not supported."
  175. fi
  176. [ -z "$(_os)" ] && _error "Not supported OS"
  177. case "$(_os)" in
  178. ubuntu)
  179. [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 16 ] && _error "Not supported OS, please change to Ubuntu 16+ and try again."
  180. ;;
  181. debian|raspbian)
  182. [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 8 ] && _error "Not supported OS, please change to De(Rasp)bian 8+ and try again."
  183. ;;
  184. fedora)
  185. [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 29 ] && _error "Not supported OS, please change to Fedora 29+ and try again."
  186. ;;
  187. centos)
  188. [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 7 ] && _error "Not supported OS, please change to CentOS 7+ and try again."
  189. ;;
  190. *)
  191. _error "Not supported OS"
  192. ;;
  193. esac
  194. }
  195. # Check linux kernel version
  196. check_kernel_version() {
  197. kernel_version="$(uname -r | cut -d- -f1)"
  198. if _version_ge ${kernel_version} 5.6.0; then
  199. return 0
  200. else
  201. return 1
  202. fi
  203. }
  204. # Install wireguard module from source
  205. install_wg_module() {
  206. get_latest_module_ver
  207. wireguard_name="wireguard-linux-compat-$(echo ${wireguard_ver} | grep -oE '[0-9.]+')"
  208. wireguard_url="https://github.com/WireGuard/wireguard-linux-compat/archive/${wireguard_ver}.tar.gz"
  209. cd ${cur_dir}
  210. _error_detect "wget --no-check-certificate -qO ${wireguard_name}.tar.gz ${wireguard_url}"
  211. _error_detect "tar zxf ${wireguard_name}.tar.gz"
  212. _error_detect "cd ${wireguard_name}/src"
  213. _error_detect "make"
  214. _error_detect "make install"
  215. _error_detect "cd ${cur_dir} && rm -fr ${wireguard_name}.tar.gz ${wireguard_name}"
  216. }
  217. # Install wireguard tools from source
  218. install_wg_tools() {
  219. get_latest_tools_ver
  220. wireguard_tools_name="wireguard-tools-$(echo ${wireguard_tools_ver} | grep -oE '[0-9.]+')"
  221. wireguard_tools_url="https://github.com/WireGuard/wireguard-tools/archive/${wireguard_tools_ver}.tar.gz"
  222. cd ${cur_dir}
  223. _error_detect "wget --no-check-certificate -qO ${wireguard_tools_name}.tar.gz ${wireguard_tools_url}"
  224. _error_detect "tar zxf ${wireguard_tools_name}.tar.gz"
  225. _error_detect "cd ${wireguard_tools_name}/src"
  226. _error_detect "make"
  227. _error_detect "make install"
  228. _error_detect "cd ${cur_dir} && rm -fr ${wireguard_tools_name}.tar.gz ${wireguard_tools_name}"
  229. }
  230. install_wg_pkgs() {
  231. _info "Install dependencies for wireguard"
  232. case "$(_os)" in
  233. ubuntu|debian|raspbian)
  234. _error_detect "apt-get update"
  235. _error_detect "apt-get -y install qrencode"
  236. _error_detect "apt-get -y install iptables"
  237. _error_detect "apt-get -y install bc"
  238. _error_detect "apt-get -y install gcc"
  239. _error_detect "apt-get -y install make"
  240. _error_detect "apt-get -y install libmnl-dev"
  241. _error_detect "apt-get -y install libelf-dev"
  242. if [ ! -d "/usr/src/linux-headers-$(uname -r)" ]; then
  243. if [ "$(_os)" = "raspbian" ]; then
  244. _error_detect "apt-get -y install raspberrypi-kernel-headers"
  245. else
  246. _error_detect "apt-get -y install linux-headers-$(uname -r)"
  247. fi
  248. fi
  249. ;;
  250. fedora)
  251. _error_detect "dnf -y install qrencode"
  252. _error_detect "dnf -y install bc"
  253. _error_detect "dnf -y install gcc"
  254. _error_detect "dnf -y install make"
  255. _error_detect "dnf -y install libmnl-devel"
  256. _error_detect "dnf -y install elfutils-libelf-devel"
  257. [ ! -d "/usr/src/kernels/$(uname -r)" ] && _error_detect "dnf -y install kernel-headers" && _error_detect "dnf -y install kernel-devel"
  258. ;;
  259. centos)
  260. _error_detect "yum -y install epel-release"
  261. _error_detect "yum -y install qrencode"
  262. _error_detect "yum -y install bc"
  263. _error_detect "yum -y install gcc"
  264. _error_detect "yum -y install make"
  265. _error_detect "yum -y install yum-utils"
  266. if [ -n "$(_os_ver)" -a "$(_os_ver)" -eq 8 ]; then
  267. yum-config-manager --enable PowerTools > /dev/null 2>&1 || yum-config-manager --enable powertools > /dev/null 2>&1
  268. fi
  269. if [ -n "$(_os_ver)" -a "$(_os_ver)" -eq 9 ]; then
  270. yum-config-manager --enable crb > /dev/null 2>&1
  271. fi
  272. _error_detect "yum -y install libmnl-devel"
  273. _error_detect "yum -y install elfutils-libelf-devel"
  274. [ ! -d "/usr/src/kernels/$(uname -r)" ] && _error_detect "yum -y install kernel-headers" && _error_detect "yum -y install kernel-devel"
  275. ;;
  276. *)
  277. ;; # do nothing
  278. esac
  279. }
  280. # Install from repository
  281. install_wg_1() {
  282. install_wg_pkgs
  283. _info "Install wireguard from repository"
  284. case "$(_os)" in
  285. ubuntu)
  286. _error_detect "apt-get update"
  287. _error_detect "apt-get -y install wireguard"
  288. ;;
  289. debian)
  290. echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
  291. printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
  292. _error_detect "apt-get update"
  293. _error_detect "apt-get -y install wireguard"
  294. ;;
  295. fedora)
  296. if [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 31 ]; then
  297. _error_detect "dnf -y copr enable jdoss/wireguard"
  298. _error_detect "dnf -y install wireguard-dkms wireguard-tools"
  299. else
  300. _error_detect "dnf -y install wireguard-tools"
  301. fi
  302. ;;
  303. centos)
  304. if [ -n "$(_os_ver)" -a "$(_os_ver)" -eq 7 ]; then
  305. _error_detect "curl -Lso /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo"
  306. fi
  307. if [ -n "$(_os_ver)" -a "$(_os_ver)" -eq 8 ]; then
  308. _error_detect "curl -Lso /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-8/jdoss-wireguard-epel-8.repo"
  309. fi
  310. _error_detect "yum -y install wireguard-dkms"
  311. _error_detect "yum -y install wireguard-tools"
  312. ;;
  313. *)
  314. ;; # do nothing
  315. esac
  316. }
  317. # Install from source
  318. install_wg_2() {
  319. install_wg_pkgs
  320. _info "Install wireguard from source"
  321. install_wg_module
  322. install_wg_tools
  323. }
  324. # Install wireguard tools from repo
  325. install_wg_3() {
  326. install_wg_pkgs
  327. _info "Install wireguard from repository"
  328. case "$(_os)" in
  329. ubuntu)
  330. _error_detect "add-apt-repository ppa:wireguard/wireguard"
  331. _error_detect "apt-get update"
  332. _error_detect "apt-get -y install --no-install-recommends wireguard-tools"
  333. ;;
  334. debian)
  335. echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
  336. printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
  337. _error_detect "apt-get update"
  338. _error_detect "apt-get -y install --no-install-recommends wireguard-tools"
  339. ;;
  340. fedora)
  341. if [ -n "$(_os_ver)" -a "$(_os_ver)" -lt 31 ]; then
  342. _error_detect "dnf -y copr enable jdoss/wireguard"
  343. _error_detect "dnf -y install wireguard-tools"
  344. else
  345. _error_detect "dnf -y install wireguard-tools"
  346. fi
  347. ;;
  348. centos)
  349. if [ -n "$(_os_ver)" -a "$(_os_ver)" -eq 7 ]; then
  350. _error_detect "curl -Lso /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo"
  351. fi
  352. if [ -n "$(_os_ver)" -a "$(_os_ver)" -eq 8 ]; then
  353. _error_detect "curl -Lso /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-8/jdoss-wireguard-epel-8.repo"
  354. fi
  355. _error_detect "yum -y install wireguard-tools"
  356. ;;
  357. *)
  358. ;; # do nothing
  359. esac
  360. }
  361. # Install wireguard tools from source
  362. install_wg_4() {
  363. install_wg_pkgs
  364. _info "Install wireguard tools from source"
  365. install_wg_tools
  366. }
  367. # Uninstall WireGuard
  368. uninstall_wg() {
  369. if ! _is_installed; then
  370. _error "WireGuard is not installed"
  371. fi
  372. _info "Uninstall WireGuard start"
  373. # stop wireguard at first
  374. _error_detect "systemctl stop wg-quick@${SERVER_WG_NIC}"
  375. _error_detect "systemctl disable wg-quick@${SERVER_WG_NIC}"
  376. # if wireguard has been installed from repository
  377. if _exists "yum" && _exists "rpm"; then
  378. if rpm -qa | grep -q wireguard-dkms; then
  379. _error_detect "yum -y remove wireguard-dkms"
  380. fi
  381. if rpm -qa | grep -q wireguard-tools; then
  382. _error_detect "yum -y remove wireguard-tools"
  383. fi
  384. elif _exists "apt" && _exists "apt-get"; then
  385. if apt list --installed | grep -q wireguard-dkms; then
  386. _error_detect "apt-get -y remove wireguard-dkms"
  387. fi
  388. if apt list --installed | grep -q wireguard-tools; then
  389. _error_detect "apt-get -y remove wireguard-tools"
  390. fi
  391. fi
  392. # if wireguard has been installed from source
  393. if _is_installed; then
  394. _error_detect "rm -f /usr/bin/wg"
  395. _error_detect "rm -f /usr/bin/wg-quick"
  396. _error_detect "rm -f /usr/share/man/man8/wg.8"
  397. _error_detect "rm -f /usr/share/man/man8/wg-quick.8"
  398. _exists "modprobe" && _error_detect "modprobe -r wireguard"
  399. fi
  400. [ -d "/etc/wireguard" ] && _error_detect "rm -fr /etc/wireguard"
  401. _info "Uninstall WireGuard completed"
  402. }
  403. # Create server interface
  404. create_server_if() {
  405. SERVER_PRIVATE_KEY="$(wg genkey)"
  406. SERVER_PUBLIC_KEY="$(echo ${SERVER_PRIVATE_KEY} | wg pubkey)"
  407. CLIENT_PRIVATE_KEY="$(wg genkey)"
  408. CLIENT_PUBLIC_KEY="$(echo ${CLIENT_PRIVATE_KEY} | wg pubkey)"
  409. CLIENT_PRE_SHARED_KEY="$( wg genpsk )"
  410. _info "Create server interface: /etc/wireguard/${SERVER_WG_NIC}.conf"
  411. [ ! -d "/etc/wireguard" ] && mkdir -p "/etc/wireguard"
  412. if [ -n "${SERVER_PUB_IPV6}" ]; then
  413. cat > /etc/wireguard/${SERVER_WG_NIC}.conf <<EOF
  414. [Interface]
  415. Address = ${SERVER_WG_IPV4}/24,${SERVER_WG_IPV6}/64
  416. ListenPort = ${SERVER_WG_PORT}
  417. PrivateKey = ${SERVER_PRIVATE_KEY}
  418. [Peer]
  419. PublicKey = ${CLIENT_PUBLIC_KEY}
  420. AllowedIPs = ${CLIENT_WG_IPV4}/32,${CLIENT_WG_IPV6}/128
  421. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  422. PersistentKeepalive = 25
  423. EOF
  424. else
  425. cat > /etc/wireguard/${SERVER_WG_NIC}.conf <<EOF
  426. [Interface]
  427. Address = ${SERVER_WG_IPV4}/24
  428. ListenPort = ${SERVER_WG_PORT}
  429. PrivateKey = ${SERVER_PRIVATE_KEY}
  430. [Peer]
  431. PublicKey = ${CLIENT_PUBLIC_KEY}
  432. AllowedIPs = ${CLIENT_WG_IPV4}/32
  433. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  434. PersistentKeepalive = 25
  435. EOF
  436. fi
  437. chmod 600 /etc/wireguard/${SERVER_WG_NIC}.conf
  438. }
  439. # Create client interface
  440. create_client_if() {
  441. _info "Create client interface: /etc/wireguard/${SERVER_WG_NIC}_client.conf"
  442. if [ -n "${SERVER_PUB_IPV6}" ]; then
  443. cat > /etc/wireguard/${SERVER_WG_NIC}_client.conf <<EOF
  444. [Interface]
  445. PrivateKey = ${CLIENT_PRIVATE_KEY}
  446. Address = ${CLIENT_WG_IPV4}/24,${CLIENT_WG_IPV6}/64
  447. DNS = ${CLIENT_DNS_1},${CLIENT_DNS_2}
  448. [Peer]
  449. PublicKey = ${SERVER_PUBLIC_KEY}
  450. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  451. AllowedIPs = 0.0.0.0/0,::/0
  452. Endpoint = ${SERVER_PUB_IPV4}:${SERVER_WG_PORT}
  453. EOF
  454. else
  455. cat > /etc/wireguard/${SERVER_WG_NIC}_client.conf <<EOF
  456. [Interface]
  457. PrivateKey = ${CLIENT_PRIVATE_KEY}
  458. Address = ${CLIENT_WG_IPV4}/24
  459. DNS = ${CLIENT_DNS_1},${CLIENT_DNS_2}
  460. [Peer]
  461. PublicKey = ${SERVER_PUBLIC_KEY}
  462. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  463. AllowedIPs = 0.0.0.0/0
  464. Endpoint = ${SERVER_PUB_IPV4}:${SERVER_WG_PORT}
  465. EOF
  466. fi
  467. chmod 600 /etc/wireguard/${SERVER_WG_NIC}_client.conf
  468. }
  469. # Generate a QR Code picture with default client interface
  470. generate_qr() {
  471. _info "Generate a QR Code picture with client interface"
  472. _error_detect "qrencode -s8 -o /etc/wireguard/${SERVER_WG_NIC}_client.png < /etc/wireguard/${SERVER_WG_NIC}_client.conf"
  473. }
  474. # Enable IP forwarding
  475. enable_ip_forward() {
  476. _info "Enable IP forward"
  477. sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf
  478. [ -n "${SERVER_PUB_IPV6}" ] && sed -i '/net.ipv6.conf.all.forwarding/d' /etc/sysctl.conf
  479. echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
  480. [ -n "${SERVER_PUB_IPV6}" ] && echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
  481. sysctl -p >/dev/null 2>&1
  482. }
  483. # Set firewall rules
  484. set_firewall() {
  485. _info "Setting firewall rules"
  486. if _exists "firewall-cmd"; then
  487. if firewall-cmd --state > /dev/null 2>&1; then
  488. default_zone="$(firewall-cmd --get-default-zone)"
  489. if [ "$(firewall-cmd --zone=${default_zone} --query-masquerade)" = "no" ]; then
  490. _error_detect "firewall-cmd --permanent --zone=${default_zone} --add-masquerade"
  491. fi
  492. if ! firewall-cmd --list-ports | grep -qw "${SERVER_WG_PORT}/udp"; then
  493. _error_detect "firewall-cmd --permanent --zone=${default_zone} --add-port=${SERVER_WG_PORT}/udp"
  494. fi
  495. _error_detect "firewall-cmd --reload"
  496. else
  497. _warn "Firewalld service unit is not running, please start it and manually set"
  498. _warn "Maybe you need to run these commands like below:"
  499. _warn "systemctl start firewalld"
  500. _warn "firewall-cmd --permanent --zone=public --add-masquerade"
  501. _warn "firewall-cmd --permanent --zone=public --add-port=${SERVER_WG_PORT}/udp"
  502. _warn "firewall-cmd --reload"
  503. fi
  504. else
  505. if _exists "iptables"; then
  506. iptables -A INPUT -p udp --dport ${SERVER_WG_PORT} -j ACCEPT
  507. iptables -A FORWARD -i ${SERVER_WG_NIC} -j ACCEPT
  508. iptables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE
  509. iptables-save > /etc/iptables.rules
  510. if [ -d "/etc/network/if-up.d" ]; then
  511. cat > /etc/network/if-up.d/iptables <<EOF
  512. #!/bin/sh
  513. /sbin/iptables-restore < /etc/iptables.rules
  514. EOF
  515. chmod +x /etc/network/if-up.d/iptables
  516. fi
  517. fi
  518. if _exists "ip6tables"; then
  519. ip6tables -A INPUT -p udp --dport ${SERVER_WG_PORT} -j ACCEPT
  520. ip6tables -A FORWARD -i ${SERVER_WG_NIC} -j ACCEPT
  521. ip6tables -t nat -A POSTROUTING -o ${SERVER_PUB_NIC} -j MASQUERADE
  522. ip6tables-save > /etc/ip6tables.rules
  523. if [ -d "/etc/network/if-up.d" ]; then
  524. cat > /etc/network/if-up.d/ip6tables <<EOF
  525. #!/bin/sh
  526. /sbin/ip6tables-restore < /etc/ip6tables.rules
  527. EOF
  528. chmod +x /etc/network/if-up.d/ip6tables
  529. fi
  530. fi
  531. fi
  532. }
  533. # WireGuard installation completed
  534. install_completed() {
  535. _info "Starting WireGuard via wg-quick for ${SERVER_WG_NIC}"
  536. _error_detect "systemctl daemon-reload"
  537. _error_detect "systemctl start wg-quick@${SERVER_WG_NIC}"
  538. _error_detect "systemctl enable wg-quick@${SERVER_WG_NIC}"
  539. _info "WireGuard VPN Server installation completed"
  540. _info ""
  541. _info "WireGuard VPN default client file is below:"
  542. _info "$(_green "/etc/wireguard/${SERVER_WG_NIC}_client.conf")"
  543. _info ""
  544. _info "WireGuard VPN default client QR Code is below:"
  545. _info "$(_green "/etc/wireguard/${SERVER_WG_NIC}_client.png")"
  546. _info ""
  547. _info "Download and scan this QR Code with your device"
  548. _info "Welcome to visit: https://teddysun.com/554.html"
  549. _info "Enjoy it"
  550. }
  551. add_client() {
  552. if ! _is_installed; then
  553. _red "WireGuard was not installed, please install it and try again\n" && exit 1
  554. fi
  555. default_server_if="/etc/wireguard/${SERVER_WG_NIC}.conf"
  556. default_client_if="/etc/wireguard/${SERVER_WG_NIC}_client.conf"
  557. [ ! -s "${default_server_if}" ] && echo "The default server interface ($(_red ${default_server_if})) does not exists" && exit 1
  558. [ ! -s "${default_client_if}" ] && echo "The default client interface ($(_red ${default_client_if})) does not exists" && exit 1
  559. while true; do
  560. read -p "Please enter a client name (for example: wg1):" client
  561. if [ -z "${client}" ]; then
  562. _red "Client name can not be empty\n"
  563. else
  564. new_client_if="/etc/wireguard/${client}_client.conf"
  565. if [ "${client}" = "${SERVER_WG_NIC}" ]; then
  566. echo "The default client ($(_yellow ${client})) already exists. Please re-enter it"
  567. elif [ -s "${new_client_if}" ]; then
  568. echo "The client ($(_yellow ${client})) already exists. Please re-enter it"
  569. else
  570. break
  571. fi
  572. fi
  573. done
  574. # Get information from default interface file
  575. client_files=($(find /etc/wireguard/ -name "*_client*" | sort))
  576. client_ipv4=()
  577. client_ipv6=()
  578. for ((i=0; i<${#client_files[@]}; i++)); do
  579. tmp_ipv4="$(grep -w "Address" ${client_files[$i]} | awk '{print $3}' | cut -d\/ -f1 )"
  580. tmp_ipv6="$(grep -w "Address" ${client_files[$i]} | awk '{print $3}' | awk -F, '{print $2}' | cut -d\/ -f1 )"
  581. client_ipv4=(${client_ipv4[@]} ${tmp_ipv4})
  582. client_ipv6=(${client_ipv6[@]} ${tmp_ipv6})
  583. done
  584. # Sort array
  585. client_ipv4_sorted=($(printf '%s\n' "${client_ipv4[@]}" | sort -V))
  586. index=$(expr ${#client_ipv4[@]} - 1)
  587. last_ip=$(echo ${client_ipv4_sorted[$index]} | cut -d. -f4)
  588. issue_ip_last=$(expr ${last_ip} + 1)
  589. [ ${issue_ip_last} -gt 254 ] && _red "Too many clients, IP addresses might be not enough\n" && exit 1
  590. ipv4_comm=$(echo ${client_ipv4[$index]} | cut -d. -f1-3)
  591. ipv6_comm=$(echo ${client_ipv6[$index]} | awk -F: '{print $1":"$2":"$3":"$4}')
  592. CLIENT_PRIVATE_KEY="$(wg genkey)"
  593. CLIENT_PUBLIC_KEY="$(echo ${CLIENT_PRIVATE_KEY} | wg pubkey)"
  594. SERVER_PUBLIC_KEY="$(grep -w "PublicKey" ${default_client_if} | awk '{print $3}')"
  595. CLIENT_ENDPOINT="$(grep -w "Endpoint" ${default_client_if} | awk '{print $3}')"
  596. CLIENT_PRE_SHARED_KEY="$(grep -w "PresharedKey" ${default_client_if} | awk '{print $3}')"
  597. CLIENT_WG_IPV4="${ipv4_comm}.${issue_ip_last}"
  598. CLIENT_WG_IPV6="${ipv6_comm}:${issue_ip_last}"
  599. # Create a new client interface
  600. if [ -n "${SERVER_PUB_IPV6}" ]; then
  601. cat > ${new_client_if} <<EOF
  602. [Interface]
  603. PrivateKey = ${CLIENT_PRIVATE_KEY}
  604. Address = ${CLIENT_WG_IPV4}/24,${CLIENT_WG_IPV6}/64
  605. DNS = ${CLIENT_DNS_1},${CLIENT_DNS_2}
  606. [Peer]
  607. PublicKey = ${SERVER_PUBLIC_KEY}
  608. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  609. AllowedIPs = 0.0.0.0/0,::/0
  610. Endpoint = ${CLIENT_ENDPOINT}
  611. EOF
  612. # Add a new client to default server interface
  613. cat >> ${default_server_if} <<EOF
  614. [Peer]
  615. PublicKey = ${CLIENT_PUBLIC_KEY}
  616. AllowedIPs = ${CLIENT_WG_IPV4}/32,${CLIENT_WG_IPV6}/128
  617. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  618. PersistentKeepalive = 25
  619. EOF
  620. else
  621. cat > ${new_client_if} <<EOF
  622. [Interface]
  623. PrivateKey = ${CLIENT_PRIVATE_KEY}
  624. Address = ${CLIENT_WG_IPV4}/24
  625. DNS = ${CLIENT_DNS_1},${CLIENT_DNS_2}
  626. [Peer]
  627. PublicKey = ${SERVER_PUBLIC_KEY}
  628. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  629. AllowedIPs = 0.0.0.0/0
  630. Endpoint = ${CLIENT_ENDPOINT}
  631. EOF
  632. cat >> ${default_server_if} <<EOF
  633. [Peer]
  634. PublicKey = ${CLIENT_PUBLIC_KEY}
  635. AllowedIPs = ${CLIENT_WG_IPV4}/32
  636. PresharedKey = ${CLIENT_PRE_SHARED_KEY}
  637. PersistentKeepalive = 25
  638. EOF
  639. fi
  640. chmod 600 ${new_client_if}
  641. echo "Add a WireGuard client ($(_green ${client})) completed"
  642. systemctl restart wg-quick@${SERVER_WG_NIC}
  643. # Generate a new QR Code picture
  644. qrencode -s8 -o /etc/wireguard/${client}_client.png < ${new_client_if}
  645. echo "Generate a QR Code picture with new client ($(_green ${client})) completed"
  646. echo
  647. echo "WireGuard VPN new client ($(_green ${client})) file is below:"
  648. _green "/etc/wireguard/${client}_client.conf\n"
  649. echo
  650. echo "WireGuard VPN new client ($(_green ${client})) QR Code is below:"
  651. _green "/etc/wireguard/${client}_client.png\n"
  652. echo "Download and scan this QR Code with your device, enjoy it"
  653. }
  654. remove_client() {
  655. if ! _is_installed; then
  656. _red "WireGuard was not installed, please install it and try again\n" && exit 1
  657. fi
  658. default_server_if="/etc/wireguard/${SERVER_WG_NIC}.conf"
  659. [ ! -s "${default_server_if}" ] && echo "The default server interface ($(_red ${default_server_if})) does not exists" && exit 1
  660. while true; do
  661. read -p "Please enter a client name you want to delete it (for example: wg1):" client
  662. if [ -z "${client}" ]; then
  663. _red "Client name can not be empty\n"
  664. else
  665. if [ "${client}" = "${SERVER_WG_NIC}" ]; then
  666. echo "The default client ($(_yellow ${client})) can not be delete"
  667. else
  668. break
  669. fi
  670. fi
  671. done
  672. client_if="/etc/wireguard/${client}_client.conf"
  673. [ ! -s "${client_if}" ] && echo "The client file ($(_red ${client_if})) does not exists" && exit 1
  674. tmp_tag="$(grep -w "Address" ${client_if} | awk '{print $3}' | cut -d\/ -f1 )"
  675. [ -n "${tmp_tag}" ] && sed -i '/'"$tmp_tag"'/,+1d;:a;1,3!{P;$!N;D};N;ba' ${default_server_if}
  676. # Delete client interface file
  677. rm -f ${client_if}
  678. [ -s "/etc/wireguard/${client}_client.png" ] && rm -f /etc/wireguard/${client}_client.png
  679. systemctl restart wg-quick@${SERVER_WG_NIC}
  680. echo "The client name ($(_green ${client})) has been deleted"
  681. }
  682. list_clients() {
  683. if ! _is_installed; then
  684. _red "WireGuard was not installed, please install it and try again\n" && exit 1
  685. fi
  686. default_server_if="/etc/wireguard/${SERVER_WG_NIC}.conf"
  687. [ ! -s "${default_server_if}" ] && echo "The default server interface ($(_red ${default_server_if})) does not exists" && exit 1
  688. local line="+-------------------------------------------------------------------------+\n"
  689. local string=%-35s
  690. printf "${line}|${string} |${string} |\n${line}" " Client Interface" " Client's IP"
  691. client_files=($(find /etc/wireguard/ -name "*_client*" | sort))
  692. ips=($(grep -w "AllowedIPs" ${default_server_if} | awk '{print $3}'))
  693. [ ${#client_files[@]} -ne ${#ips[@]} ] && echo "One or more client interface file is missing in /etc/wireguard" && exit 1
  694. for ((i=0; i<${#ips[@]}; i++)); do
  695. tmp_ipv4="$(echo ${ips[$i]} | cut -d\/ -f1)"
  696. for ((j=0; j<${#client_files[@]}; j++)); do
  697. if grep -qw "${tmp_ipv4}" "${client_files[$j]}"; then
  698. printf "|${string} |${string} |\n" " ${client_files[$j]}" " ${ips[$i]}"
  699. break
  700. fi
  701. done
  702. done
  703. printf ${line}
  704. }
  705. check_version() {
  706. _is_installed
  707. rt=$?
  708. if [ ${rt} -eq 0 ]; then
  709. _exists "modinfo" && installed_wg_ver="$(modinfo -F version wireguard)"
  710. [ -n "${installed_wg_ver}" ] && echo "wireguard-dkms version : $(_green ${installed_wg_ver})"
  711. installed_wg_tools_ver="$(wg --version | awk '{print $2}' | grep -oE '[0-9.]+')"
  712. [ -n "${installed_wg_tools_ver}" ] && echo "wireguard-tools version: $(_green ${installed_wg_tools_ver})"
  713. return 0
  714. elif [ ${rt} -eq 1 ]; then
  715. _red "WireGuard tools is exist, but WireGuard module does not exists\n" && return 1
  716. elif [ ${rt} -eq 2 ]; then
  717. _red "WireGuard module is exist, but WireGuard tools does not exists\n" && return 2
  718. elif [ ${rt} -eq 3 ]; then
  719. _red "WireGuard was not installed\n" && return 3
  720. fi
  721. }
  722. show_help() {
  723. printf "
  724. Usage : $0 [Options]
  725. Options:
  726. -h, --help Print this help text and exit
  727. -r, --repo Install WireGuard from repository
  728. -s, --source Install WireGuard from source
  729. -u, --update Upgrade WireGuard from source
  730. -v, --version Print WireGuard version if installed
  731. -a, --add Add a WireGuard client
  732. -d, --del Delete a WireGuard client
  733. -l, --list List all WireGuard client's IP
  734. -n, --uninstall Uninstall WireGuard
  735. "
  736. }
  737. install_from_repo() {
  738. _is_installed
  739. rt=$?
  740. if [ ${rt} -eq 0 ]; then
  741. _red "WireGuard was already installed\n" && exit 0
  742. fi
  743. check_os
  744. if check_kernel_version; then
  745. if [ ${rt} -eq 2 ]; then
  746. install_wg_3
  747. else
  748. _error "WireGuard module does not exists, please check your kernel"
  749. fi
  750. else
  751. install_wg_1
  752. fi
  753. create_server_if
  754. create_client_if
  755. generate_qr
  756. enable_ip_forward
  757. set_firewall
  758. install_completed
  759. }
  760. install_from_source() {
  761. _is_installed
  762. rt=$?
  763. if [ ${rt} -eq 0 ]; then
  764. _red "WireGuard was already installed\n" && exit 0
  765. fi
  766. check_os
  767. if check_kernel_version; then
  768. if [ ${rt} -eq 2 ]; then
  769. install_wg_4
  770. else
  771. _error "WireGuard module does not exists, please check your kernel"
  772. fi
  773. else
  774. install_wg_2
  775. fi
  776. create_server_if
  777. create_client_if
  778. generate_qr
  779. enable_ip_forward
  780. set_firewall
  781. install_completed
  782. }
  783. update_from_source() {
  784. if check_version > /dev/null 2>&1; then
  785. restart_flg=0
  786. get_latest_module_ver
  787. wg_ver="$(echo ${wireguard_ver} | grep -oE '[0-9.]+')"
  788. _info "wireguard-dkms version: $(_green ${installed_wg_ver})"
  789. _info "wireguard-dkms latest version: $(_green ${wg_ver})"
  790. if check_kernel_version; then
  791. _info "wireguard-dkms has been merged into Linux >= 5.6 and therefore this compatibility module is no longer required"
  792. else
  793. if _version_gt "${wg_ver}" "${installed_wg_ver}"; then
  794. _info "Starting upgrade wireguard-dkms"
  795. install_wg_module
  796. _info "Update wireguard-dkms completed"
  797. restart_flg=1
  798. else
  799. _info "There is no update available for wireguard-dkms"
  800. fi
  801. fi
  802. get_latest_tools_ver
  803. wg_tools_ver="$(echo ${wireguard_tools_ver} | grep -oE '[0-9.]+')"
  804. _info "wireguard-tools version: $(_green ${installed_wg_tools_ver})"
  805. _info "wireguard-tools latest version: $(_green ${wg_tools_ver})"
  806. if _version_gt "${wg_tools_ver}" "${installed_wg_tools_ver}"; then
  807. _info "Starting upgrade wireguard-tools"
  808. install_wg_tools
  809. _info "Update wireguard-tools completed"
  810. restart_flg=1
  811. else
  812. _info "There is no update available for wireguard-tools"
  813. fi
  814. if [ ${restart_flg} -eq 1 ]; then
  815. _error_detect "systemctl daemon-reload"
  816. _error_detect "systemctl restart wg-quick@${SERVER_WG_NIC}"
  817. fi
  818. else
  819. _red "WireGuard was not installed, maybe you need to install it at first\n"
  820. fi
  821. }
  822. main() {
  823. action="$1"
  824. [ -z "${action}" ] && show_help && exit 0
  825. case "${action}" in
  826. -h|--help)
  827. show_help
  828. ;;
  829. -r|--repo)
  830. install_from_repo
  831. ;;
  832. -s|--source)
  833. install_from_source
  834. ;;
  835. -u|--update)
  836. update_from_source
  837. ;;
  838. -v|--version)
  839. check_version
  840. ;;
  841. -a|--add)
  842. add_client
  843. ;;
  844. -d|--del)
  845. remove_client
  846. ;;
  847. -l|--list)
  848. list_clients
  849. ;;
  850. -n|--uninstall)
  851. uninstall_wg
  852. ;;
  853. *)
  854. show_help
  855. ;;
  856. esac
  857. }
  858. SERVER_PUB_IPV4="${VPN_SERVER_PUB_IPV4:-$(_ipv4)}"
  859. SERVER_PUB_IPV6="${VPN_SERVER_PUB_IPV6:-$(_ipv6)}"
  860. SERVER_PUB_NIC="${VPN_SERVER_PUB_NIC:-$(_nic)}"
  861. SERVER_WG_NIC="${VPN_SERVER_WG_NIC:-wg0}"
  862. SERVER_WG_IPV4="${VPN_SERVER_WG_IPV4:-10.88.88.1}"
  863. SERVER_WG_IPV6="${VPN_SERVER_WG_IPV6:-fd88:88:88::1}"
  864. SERVER_WG_PORT="${VPN_SERVER_WG_PORT:-$(_port)}"
  865. CLIENT_WG_IPV4="${VPN_CLIENT_WG_IPV4:-10.88.88.2}"
  866. CLIENT_WG_IPV6="${VPN_CLIENT_WG_IPV6:-fd88:88:88::2}"
  867. CLIENT_DNS_1="${VPN_CLIENT_DNS_1:-1.1.1.1}"
  868. CLIENT_DNS_2="${VPN_CLIENT_DNS_2:-8.8.8.8}"
  869. main "$@"