]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/scripts/ipsec-interfaces
strongswan: Manually install all routes for non-routed VPNs
[people/pmueller/ipfire-2.x.git] / src / scripts / ipsec-interfaces
CommitLineData
b8c153bc
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2015 IPFire Team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
22shopt -s nullglob
23
24VPN_CONFIG="/var/ipfire/vpn/config"
25
d66433fc
MT
26ROUTE_TABLE="220"
27ROUTE_TABLE_PRIO="128"
28
54bac014 29eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)
b8c153bc
MT
30eval $(/usr/local/bin/readhash /var/ipfire/vpn/settings)
31
d66433fc
MT
32# Get RED interface name
33if [ -r "/var/ipfire/red/iface" ]; then
34 RED_INTF="$(</var/ipfire/red/iface)"
35else
36 RED_INTF="red0"
37fi
38
b8c153bc 39VARS=(
68263645
MT
40 id status name lefthost type ctype psk local local_id leftsubnets
41 remote_id remote rightsubnets x3 x4 x5 x6 x7 x8 x9 x10 x11 x12
1ca2f88a
MT
42 x13 x14 x15 x16 x17 x18 x19 proto x20 x21 x22
43 route x23 mode interface_mode interface_address interface_mtu rest
b8c153bc
MT
44)
45
46log() {
47 logger -t ipsec "$@"
48}
49
f9dd1346
MT
50resolve_hostname() {
51 local hostname="${1}"
52
53 dig +short A "${hostname}" | tail -n1
54}
55
d66433fc
MT
56ip_encode() {
57 local address="${1}"
58
59 local int=0
60 for field in ${address//./ }; do
61 int=$(( $(( ${int} << 8 )) | ${field} ))
62 done
63
64 echo ${int}
65}
66
67function ip_in_subnet() {
68 local address="${1}"
69 local subnet="${2}"
70
71 local netmask="${subnet#*/}"
72
73 # Convert netmask to prefix if necessary
74 case "${netmask}" in
75 [0-9]+)
76 ;;
77 *)
78 netmask="$(netmask2prefix "${netmask}")"
79 ;;
80 esac
81
82 local vlsm=$(( -1 << $(( 32 - ${netmask} )) ))
83
84 [ "$(( $(ip_encode "${address}") & ${vlsm} ))" -eq "$(( $(ip_encode "${subnet%/*}") & ${vlsm} ))" ]
85}
86
87netmask2prefix() {
88 local netmask="${1}"
89 local mask="$(ip_encode "${netmask}")"
90
91 local cidr=0
92 local x="$(( 128 << 24 ))" # 0x80000000
93
94 while [ $(( ${x} & ${mask} )) -ne 0 ]; do
95 [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 ))
96 cidr=$(( ${cidr} + 1 ))
97 done
98
99 echo "${cidr}"
100}
101
b8c153bc 102main() {
b8c153bc
MT
103 # Register local variables
104 local "${VARS[@]}"
105 local action
106
107 local interfaces=()
1ca2f88a 108
d66433fc
MT
109 # Flush IPsec routes
110 ip route flush table "${ROUTE_TABLE}"
111
112 # Remove lookups
113 ip rule del lookup "${ROUTE_TABLE}"
114
1a45f9a7
MT
115 # We are done when IPsec is not enabled
116 if [ "${ENABLED}" = "on" ]; then
d66433fc
MT
117 # Enable route table lookup
118 ip rule add lookup "${ROUTE_TABLE}" prio "${ROUTE_TABLE_PRIO}"
119
1a45f9a7
MT
120 while IFS="," read -r "${VARS[@]}"; do
121 # Check if the connection is enabled
122 [ "${status}" = "on" ] || continue
123
124 # Check if this a net-to-net connection
125 [ "${type}" = "net" ] || continue
126
127 # Determine the interface name
128 case "${interface_mode}" in
129 gre|vti)
130 local intf="${interface_mode}${id}"
131 ;;
132 *)
d66433fc
MT
133 # Install routes
134 local address
135
136 local _address
137 for _address in ${GREEN_ADDRESS} ${BLUE_ADDRESS} ${ORANGE_ADDRESS}; do
138 local leftsubnet
139 for leftsubnet in ${leftsubnets//\|/ }; do
140 if ip_in_subnet "${_address}" "${leftsubnet}"; then
141 address="${_address}"
142 break
143 fi
144 done
145
146 # End loop when address is set
147 [ -n "${address}" ] && break
148 done
149
150 local rightsubnet
151 for rightsubnet in ${rightsubnets//\|/ }; do
152 # Ignore default
153 case "${rightsubnet}" in
154 0.0.0.0/*)
155 continue
156 ;;
157 esac
158
159 log "Creating route to ${rightsubnet} (via ${address} and ${RED_INTF})"
160 ip route add table "${ROUTE_TABLE}" "${rightsubnet}" proto static \
161 dev "${RED_INTF}" src "${address}"
162 done
163
164 # No interface processing required
1a45f9a7
MT
165 continue
166 ;;
167 esac
168
169 # Add the interface to the list of all interfaces
170 interfaces+=( "${intf}" )
171
d985ce5a
MT
172 # Compat for older connections
173 if [ "${local}" = "off" ]; then
174 if [ "${VPN_IP}" = "%defaultroute" ]; then
175 local=""
176 else
177 local="${VPN_IP}"
178 fi
179 fi
180
181 # Handle %defaultroute
182 if [ -z "${local}" ]; then
183 if [ -r "/var/ipfire/red/local-ipaddress" ]; then
184 local="$(</var/ipfire/red/local-ipaddress)"
185
186 elif [ "${RED_TYPE}" = "STATIC" -a -n "${RED_ADDRESS}" ]; then
187 local="${RED_ADDRESS}"
188 fi
189 fi
190
f9dd1346
MT
191 # Resolve any hostnames
192 if [[ ! ${remote} =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
193 remote="$(resolve_hostname "${remote}")"
194 fi
195
1a45f9a7 196 local args=(
1ca2f88a
MT
197 "local" "${local}"
198 "remote" "${remote}"
1a45f9a7
MT
199 )
200
6a45a1f1
MT
201 case "${interface_mode}" in
202 gre)
203 # Add TTL
204 args+=( "ttl" "255" )
205 ;;
206
207 vti)
208 # Add key for VTI
209 args+=( "key" "${id}" )
210 ;;
211 esac
b8c153bc 212
1a45f9a7
MT
213 # Update the settings when the interface already exists
214 if [ -d "/sys/class/net/${intf}" ]; then
215 ip link change dev "${intf}" \
216 type "${interface_mode}" "${args[@]}" &>/dev/null
b8c153bc 217
1a45f9a7
MT
218 # Create a new interface and bring it up
219 else
220 log "Creating interface ${intf}"
3dc21d43
MT
221 if ! ip link add name "${intf}" type "${interface_mode}" "${args[@]}"; then
222 log "Could not create interface ${intf}"
223 continue
224 fi
1a45f9a7
MT
225 fi
226
227 # Add an IP address
228 ip addr flush dev "${intf}"
229 ip addr add "${interface_address}" dev "${intf}"
230
231 # Set MTU
232 ip link set dev "${intf}" mtu "${interface_mtu}"
b8c153bc 233
1a45f9a7
MT
234 # Bring up the interface
235 ip link set dev "${intf}" up
236 done < "${VPN_CONFIG}"
237 fi
b8c153bc
MT
238
239 # Delete all other interfaces
240 local intf
c821440c 241 for intf in /sys/class/net/gre[0-9]* /sys/class/net/vti[0-9]*; do
b8c153bc
MT
242 intf="$(basename "${intf}")"
243
244 # Ignore a couple of interfaces that cannot be deleted
245 case "${intf}" in
246 gre0|gretap0)
247 continue
248 ;;
249 esac
250
251 # Check if interface is on the list
252 local i found="false"
253 for i in ${interfaces[@]}; do
254 if [ "${intf}" = "${i}" ]; then
255 found="true"
256 break
257 fi
258 done
259
260 # Nothing to do if interface was found
261 ${found} && continue
262
263 # Delete the interface
264 log "Deleting interface ${intf}"
265 ip link del "${intf}" &>/dev/null
266 done
a485606c
MT
267
268 # (Re-)Apply all static routes
269 /etc/init.d/static-routes start
b8c153bc
MT
270}
271
272main || exit $?