96fa7215ffc8d47e2f7934a96ada21eee5a4ed19
[librecmc/librecmc.git] / package / network / services / wireguard / files / wireguard.sh
1 #!/bin/sh
2 # Copyright 2016-2017 Dan Luedtke <mail@danrl.com>
3 # Licensed to the public under the Apache License 2.0.
4
5
6 WG=/usr/bin/wg
7 if [ ! -x $WG ]; then
8   logger -t "wireguard" "error: missing wireguard-tools (${WG})"
9   exit 0
10 fi
11
12
13 [ -n "$INCLUDE_ONLY" ] || {
14   . /lib/functions.sh
15   . ../netifd-proto.sh
16   init_proto "$@"
17 }
18
19
20 proto_wireguard_init_config() {
21   proto_config_add_string "private_key"
22   proto_config_add_int    "listen_port"
23   proto_config_add_int    "mtu"
24   proto_config_add_string "fwmark"
25   available=1
26   no_proto_task=1
27 }
28
29
30 proto_wireguard_setup_peer() {
31   local peer_config="$1"
32
33   local public_key
34   local preshared_key
35   local allowed_ips
36   local route_allowed_ips
37   local endpoint_host
38   local endpoint_port
39   local persistent_keepalive
40
41   config_get      public_key           "${peer_config}" "public_key"
42   config_get      preshared_key        "${peer_config}" "preshared_key"
43   config_get      allowed_ips          "${peer_config}" "allowed_ips"
44   config_get_bool route_allowed_ips    "${peer_config}" "route_allowed_ips" 0
45   config_get      endpoint_host        "${peer_config}" "endpoint_host"
46   config_get      endpoint_port        "${peer_config}" "endpoint_port"
47   config_get      persistent_keepalive "${peer_config}" "persistent_keepalive"
48
49   # peer configuration
50   echo "[Peer]"                                         >> "${wg_cfg}"
51   echo "PublicKey=${public_key}"                        >> "${wg_cfg}"
52   if [ "${preshared_key}" ]; then
53     echo "PresharedKey=${preshared_key}"                >> "${wg_cfg}"
54   fi
55   for allowed_ip in $allowed_ips; do
56     echo "AllowedIPs=${allowed_ip}"                     >> "${wg_cfg}"
57   done
58   if [ "${endpoint_host}" ]; then
59     case "${endpoint_host}" in
60       *:*)
61         endpoint="[${endpoint_host}]"
62       ;;
63       *)
64         endpoint="${endpoint_host}"
65       ;;
66     esac
67     if [ "${endpoint_port}" ]; then
68       endpoint="${endpoint}:${endpoint_port}"
69     else
70       endpoint="${endpoint}:51820"
71     fi
72     echo "Endpoint=${endpoint}"                         >> "${wg_cfg}"
73   fi
74   if [ "${persistent_keepalive}" ]; then
75     echo "PersistentKeepalive=${persistent_keepalive}"  >> "${wg_cfg}"
76   fi
77
78   # add routes for allowed ips
79   if [ ${route_allowed_ips} -ne 0 ]; then
80     for allowed_ip in ${allowed_ips}; do
81       case "${allowed_ip}" in
82         *:*/*)
83           proto_add_ipv6_route "${allowed_ip%%/*}" "${allowed_ip##*/}"
84         ;;
85         *.*/*)
86           proto_add_ipv4_route "${allowed_ip%%/*}" "${allowed_ip##*/}"
87         ;;
88         *:*)
89           proto_add_ipv6_route "${allowed_ip%%/*}" "128"
90         ;;
91         *.*)
92           proto_add_ipv4_route "${allowed_ip%%/*}" "32"
93         ;;
94       esac
95     done
96   fi
97 }
98
99
100 proto_wireguard_setup() {
101   local config="$1"
102   local wg_dir="/tmp/wireguard"
103   local wg_cfg="${wg_dir}/${config}"
104
105   local private_key
106   local listen_port
107   local mtu
108
109   # load configuration
110   config_load network
111   config_get private_key   "${config}" "private_key"
112   config_get listen_port   "${config}" "listen_port"
113   config_get addresses     "${config}" "addresses"
114   config_get mtu           "${config}" "mtu"
115   config_get fwmark        "${config}" "fwmark"
116   config_get ip6prefix     "${config}" "ip6prefix"
117
118   # create interface
119   ip link del dev "${config}" 2>/dev/null
120   ip link add dev "${config}" type wireguard
121
122   if [ "${mtu}" ]; then
123     ip link set mtu "${mtu}" dev "${config}"
124   fi
125
126   proto_init_update "${config}" 1
127
128   # generate configuration file
129   umask 077
130   mkdir -p "${wg_dir}"
131   echo "[Interface]"                     >  "${wg_cfg}"
132   echo "PrivateKey=${private_key}"       >> "${wg_cfg}"
133   if [ "${listen_port}" ]; then
134     echo "ListenPort=${listen_port}"     >> "${wg_cfg}"
135   fi
136   if [ "${fwmark}" ]; then
137     echo "FwMark=${fwmark}" >> "${wg_cfg}"
138   fi
139   config_foreach proto_wireguard_setup_peer "wireguard_${config}"
140
141   # apply configuration file
142   ${WG} setconf ${config} "${wg_cfg}"
143   WG_RETURN=$?
144
145   # delete configuration file
146   rm -f "${wg_cfg}"
147
148   # check status
149   if [ ${WG_RETURN} -ne 0 ]; then
150     sleep 5
151     proto_setup_failed "${config}"
152     exit 1
153   fi
154
155   # add ip addresses
156   for address in ${addresses}; do
157     case "${address}" in
158       *:*/*)
159         proto_add_ipv6_address "${address%%/*}" "${address##*/}"
160       ;;
161       *.*/*)
162         proto_add_ipv4_address "${address%%/*}" "${address##*/}"
163       ;;
164       *:*)
165         proto_add_ipv6_address "${address%%/*}" "128"
166       ;;
167       *.*)
168         proto_add_ipv4_address "${address%%/*}" "32"
169       ;;
170     esac
171   done
172
173   # support ip6 prefixes
174   for prefix in ${ip6prefix}; do
175       proto_add_ipv6_prefix "$prefix"
176   done
177
178   # endpoint dependency
179   wg show "${config}" endpoints | \
180     sed -E 's/\[?([0-9.:a-f]+)\]?:([0-9]+)/\1 \2/' | \
181     while IFS=$'\t ' read -r key address port; do
182     [ -n "${port}" ] || continue
183     proto_add_host_dependency "${config}" "${address}"
184   done
185
186   proto_send_update "${config}"
187 }
188
189
190 proto_wireguard_teardown() {
191   local config="$1"
192   ip link del dev "${config}" >/dev/null 2>&1
193 }
194
195
196 [ -n "$INCLUDE_ONLY" ] || {
197   add_protocol wireguard
198 }