sshtunnel: ProxyCommand option
[feed/packages.git] / net / sshtunnel / files / sshtunnel.init
1 #!/bin/sh /etc/rc.common
2 #
3 # Copyright (C) 2010-2015 OpenWrt.org
4 # Copyright (C) 2010 segal.di.ubi.pt
5 #
6
7 START=99
8 STOP=01
9 USE_PROCD=1
10
11 PROG=/usr/bin/ssh
12
13 _log() {
14 logger -p daemon.info -t sshtunnel "$@"
15 }
16
17 _err() {
18 logger -p daemon.err -t sshtunnel "$@"
19 }
20
21 append_params() {
22 local p v args
23 for p in "$@"; do
24 eval "v=\$$p"
25 [ -n "$v" ] && args="$args -o $p=$v"
26 done
27
28 ARGS_options="${args# *}"
29 }
30
31 append_string() {
32 local varname="$1"; local add="$2"; local separator="${3:- }"; local actual new
33 eval "actual=\$$varname"
34
35 new="${actual:+$actual$separator}$add"
36 eval "$varname=\$new"
37 }
38
39 validate_server_section() {
40 uci_load_validate sshtunnel server "$1" "$2" \
41 'user:string(1)' \
42 'hostname:host' \
43 'port:port' \
44 'retrydelay:min(1):60' \
45 'PKCS11Provider:file' \
46 'CheckHostIP:or("yes", "no")' \
47 'Compression:or("yes", "no")' \
48 'CompressionLevel:range(1,9)' \
49 'IdentityFile:file' \
50 'LogLevel:or("QUIET", "FATAL", "ERROR", "INFO", "VERBOSE", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3")' \
51 'ServerAliveCountMax:min(1)' \
52 'ServerAliveInterval:min(0)' \
53 'StrictHostKeyChecking:or("yes", "no", "accept-new"):accept-new' \
54 'TCPKeepAlive:or("yes", "no")' \
55 'VerifyHostKeyDNS:or("yes", "no")' \
56 'ProxyCommand:string(1)'
57 }
58
59 validate_tunnelR_section() {
60 uci_load_validate sshtunnel tunnelR "$1" "$2" \
61 'enabled:bool:1' \
62 'remoteaddress:or(host, "*")' \
63 'remoteport:port' \
64 'localaddress:host' \
65 'localport:port'
66 }
67
68 validate_tunnelL_section() {
69 uci_load_validate sshtunnel tunnelL "$1" "$2" \
70 'enabled:bool:1' \
71 'remoteaddress:host' \
72 'remoteport:port' \
73 'localaddress:or(host, "*")' \
74 'localport:port'
75 }
76
77 validate_tunnelD_section() {
78 uci_load_validate sshtunnel tunnelD "$1" "$2" \
79 'enabled:bool:1' \
80 'localaddress:or(host, "*")' \
81 'localport:port'
82 }
83
84 validate_tunnelW_section() {
85 uci_load_validate sshtunnel tunnelW "$1" "$2" \
86 'enabled:bool:1' \
87 'vpntype:or("ethernet", "point-to-point"):point-to-point' \
88 'localdev:or("any", min(0))' \
89 'remotedev:or("any", min(0))'
90 }
91
92 load_tunnelR() {
93 config_get section_server "$1" "server"
94 [ "$enabled" = 0 ] && return 0
95
96 # continue to read next section if this is not for the current server
97 [ "$server" = "$section_server" ] || return 0
98
99 # validate and load this remote tunnel config
100 [ "$2" = 0 ] || { _err "tunnelR $1: validation failed"; return 1; }
101
102 [ -n "$remoteport" -a -n "$localport" ] || { _err "tunnelR $1: missing required options"; return 1; }
103
104 # count nr of valid sections to make sure there are at least one
105 count=$((count+=1))
106
107 _log "tunnelR at $server: -R $remoteaddress:$remoteport:$localaddress:$localport"
108 append_string "ARGS_tunnels" "-R $remoteaddress:$remoteport:$localaddress:$localport"
109 }
110
111 load_tunnelL() {
112 config_get section_server "$1" "server"
113 [ "$enabled" = 0 ] && return 0
114
115 # continue to read next section if this is not for the current server
116 [ "$server" = "$section_server" ] || return 0
117
118 # validate and load this remote tunnel config
119 [ "$2" = 0 ] || { _err "tunnelL $1: validation failed"; return 1; }
120
121 [ -n "$remoteport" -a -n "$localport" ] || { _err "tunnelL $1: missing required options"; return 1; }
122
123 # count nr of valid sections to make sure there are at least one
124 count=$((count+=1))
125
126 _log "tunnelL at $server: -L $localaddress:$localport:$remoteaddress:$remoteport"
127 append_string "ARGS_tunnels" "-L $localaddress:$localport:$remoteaddress:$remoteport"
128 }
129
130 load_tunnelD() {
131 config_get section_server "$1" "server"
132 [ "$enabled" = 0 ] && return 0
133
134 # continue to read next section if this is not for the current server
135 [ "$server" = "$section_server" ] || return 0
136
137 # validate and load this remote tunnel config
138 [ "$2" = 0 ] || { _err "tunnelD $1: validation failed"; return 1; }
139
140 [ -n "$localport" ] || { _err "tunnelD $1: missing localport"; return 1; }
141
142 # count nr of valid sections to make sure there are at least one
143 count=$((count+=1))
144
145 _log "proxy via $server: -D $localaddress:$localport"
146 append_string "ARGS_tunnels" "-D $localaddress:$localport"
147 }
148
149 load_tunnelW() {
150 config_get section_server "$1" "server"
151 [ "$enabled" = 0 ] && return 0
152
153 # continue to read next section if this is not for the current server
154 [ "$server" = "$section_server" ] || return 0
155
156 # validate and load this remote tunnel config
157 [ "$2" = 0 ] || { _err "tunnelW $1: validation failed"; return 1; }
158
159 [ -n "$vpntype" -a -n "$localdev" -a -n "$remotedev" ] || { _err "tunnelW $1: missing or bad options"; return 1; }
160
161 [ "$user" = "root" ] || { _err "tunnelW $1: root is required for tun"; return 1; }
162
163 # count nr of valid sections to make sure there are at least one
164 count=$((count+=1))
165
166 _log "tunnelW to $server: -o Tunnel=$vpntype -w $localdev:$remotedev"
167 append_string "ARGS_tunnels" "-o Tunnel=$vpntype -w $localdev:$remotedev"
168 }
169
170 load_server() {
171 local server="$1"
172
173 [ "$2" = 0 ] || { _err "server $server: validation failed"; return 1; }
174
175 local ARGS=""
176 local ARGS_options=""
177 local ARGS_tunnels=""
178 local count=0
179
180 config_foreach validate_tunnelR_section "tunnelR" load_tunnelR
181 config_foreach validate_tunnelL_section "tunnelL" load_tunnelL
182 config_foreach validate_tunnelD_section "tunnelD" load_tunnelD
183 config_foreach validate_tunnelW_section "tunnelW" load_tunnelW
184 [ "$count" -eq 0 ] && { _err "tunnels to $server not started - no tunnels defined"; return 1; }
185
186 append_params CheckHostIP Compression CompressionLevel \
187 LogLevel PKCS11Provider ServerAliveCountMax ServerAliveInterval \
188 StrictHostKeyChecking TCPKeepAlive VerifyHostKeyDNS
189
190 # dropbear doesn't support -o IdentityFile so use -i instead
191 [ -n "$IdentityFile" ] && ARGS_options="$ARGS_options -i $IdentityFile"
192 # dbclient doesn't support StrictHostKeyChecking but it has the -y option that works same
193 [ "$StrictHostKeyChecking" = "accept-new" ] && ARGS_options="$ARGS_options -y"
194 [ "$StrictHostKeyChecking" = "no" ] && ARGS_options="$ARGS_options -yy"
195 ARGS="$ARGS_options -o ExitOnForwardFailure=yes -o BatchMode=yes -nN $ARGS_tunnels "
196 [ -n "$port" ] && ARGS="$ARGS -p $port "
197 [ -n "$user" ] && ARGS="$ARGS $user@"
198 ARGS="${ARGS}$hostname"
199
200 procd_open_instance "$server"
201 procd_set_param command "$PROG" $ARGS
202 # ProxyCommand must be quoted
203 [ -n "$ProxyCommand" ] && procd_append_param command -o "ProxyCommand=$ProxyCommand"
204
205 procd_set_param stdout 1
206 procd_set_param stderr 1
207 procd_set_param respawn 0 "$retrydelay" 1
208 procd_close_instance
209 }
210
211 start_service() {
212 config_load "sshtunnel"
213 config_foreach validate_server_section "server" load_server
214 }
215
216 service_triggers() {
217 procd_add_reload_trigger "sshtunnel"
218
219 procd_open_validate
220 validate_server_section
221 validate_tunnelR_section
222 validate_tunnelL_section
223 validate_tunnelD_section
224 validate_tunnelW_section
225 procd_close_validate
226 }