1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import logging 6 7 from autotest_lib.client.bin import utils 8 from autotest_lib.client.cros import network_chroot 9 from autotest_lib.client.common_lib.cros import site_eap_certs 10 11 class VPNServer(object): 12 """Context enclosing the use of a VPN server instance.""" 13 14 def __enter__(self): 15 self.start_server() 16 return self 17 18 19 def __exit__(self, exception, value, traceback): 20 logging.info('Log contents: %s', self.get_log_contents()) 21 self.stop_server() 22 23 24 class L2TPIPSecVPNServer(VPNServer): 25 """Implementation of an L2TP/IPSec VPN. Uses ipsec starter and xl2tpd.""" 26 PRELOAD_MODULES = ('af_key', 'ah4', 'esp4', 'ipcomp', 'xfrm_user', 27 'xfrm4_tunnel') 28 ROOT_DIRECTORIES = ('etc/ipsec.d', 'etc/ipsec.d/cacerts', 29 'etc/ipsec.d/certs', 'etc/ipsec.d/crls', 30 'etc/ipsec.d/private', 'etc/ppp', 'etc/xl2tpd') 31 CHAP_USER = 'chapuser' 32 CHAP_SECRET = 'chapsecret' 33 IPSEC_COMMAND = '/usr/sbin/ipsec' 34 IPSEC_LOGFILE = 'var/log/charon.log' 35 IPSEC_PRESHARED_KEY = 'preshared-key' 36 IPSEC_CA_CERTIFICATE = 'etc/ipsec.d/cacerts/ca.cert' 37 IPSEC_SERVER_CERTIFICATE = 'etc/ipsec.d/certs/server.cert' 38 PPPD_PID_FILE = 'run/ppp0.pid' 39 XAUTH_USER = 'xauth_user' 40 XAUTH_PASSWORD = 'xauth_password' 41 XAUTH_SECONDARY_AUTHENTICATION_STANZA = 'rightauth2=xauth' 42 XL2TPD_COMMAND = '/usr/sbin/xl2tpd' 43 XL2TPD_CONFIG_FILE = 'etc/xl2tpd/xl2tpd.conf' 44 XL2TPD_PID_FILE = 'run/xl2tpd.pid' 45 SERVER_IP_ADDRESS = '192.168.1.99' 46 IPSEC_COMMON_CONFIGS = { 47 'etc/strongswan.conf' : 48 'charon {\n' 49 ' filelog {\n' 50 ' %(charon-logfile)s {\n' 51 ' time_format = %%b %%e %%T\n' 52 ' default = 3\n' 53 ' }\n' 54 ' }\n' 55 ' install_routes = no\n' 56 ' ignore_routing_tables = 0\n' 57 ' routing_table = 0\n' 58 '}\n', 59 60 'etc/passwd' : 61 'root:x:0:0:root:/root:/bin/bash\n' 62 'ipsec:*:212:212::/dev/null:/bin/false\n', 63 64 'etc/group' : 65 'ipsec:x:212:\n', 66 67 XL2TPD_CONFIG_FILE : 68 '[global]\n' 69 '\n' 70 '[lns default]\n' 71 ' ip range = 192.168.1.128-192.168.1.254\n' 72 ' local ip = 192.168.1.99\n' 73 ' require chap = yes\n' 74 ' refuse pap = yes\n' 75 ' require authentication = yes\n' 76 ' name = LinuxVPNserver\n' 77 ' ppp debug = yes\n' 78 ' pppoptfile = /etc/ppp/options.xl2tpd\n' 79 ' length bit = yes\n', 80 81 'etc/xl2tpd/l2tp-secrets' : 82 '* them l2tp-secret', 83 84 'etc/ppp/chap-secrets' : 85 '%(chap-user)s * %(chap-secret)s *', 86 87 'etc/ppp/options.xl2tpd' : 88 'ipcp-accept-local\n' 89 'ipcp-accept-remote\n' 90 'noccp\n' 91 'auth\n' 92 'crtscts\n' 93 'idle 1800\n' 94 'mtu 1410\n' 95 'mru 1410\n' 96 'nodefaultroute\n' 97 'debug\n' 98 'lock\n' 99 'proxyarp\n' 100 } 101 IPSEC_TYPED_CONFIGS = { 102 'psk': { 103 'etc/ipsec.conf' : 104 'config setup\n' 105 ' charondebug="%(charon-debug-flags)s"\n' 106 'conn L2TP\n' 107 ' keyexchange=ikev1\n' 108 ' ike=aes128-sha1-modp2048!\n' 109 ' esp=3des-sha1!\n' 110 ' type=transport\n' 111 ' authby=psk\n' 112 ' %(xauth-stanza)s\n' 113 ' rekey=no\n' 114 ' left=%(local-ip)s\n' 115 ' leftprotoport=17/1701\n' 116 ' right=%%any\n' 117 ' rightprotoport=17/%%any\n' 118 ' auto=add\n', 119 120 'etc/ipsec.secrets' : 121 '%(local-ip)s %%any : PSK "%(preshared-key)s"\n' 122 '%(xauth-user)s : XAUTH "%(xauth-password)s"\n', 123 }, 124 'cert': { 125 'etc/ipsec.conf' : 126 'config setup\n' 127 ' charondebug="%(charon-debug-flags)s"\n' 128 'conn L2TP\n' 129 ' keyexchange=ikev1\n' 130 ' ike=aes128-sha1-modp2048!\n' 131 ' esp=3des-sha1!\n' 132 ' type=transport\n' 133 ' left=%(local-ip)s\n' 134 ' leftcert=server.cert\n' 135 ' leftid="C=US, ST=California, L=Mountain View, ' 136 'CN=chromelab-wifi-testbed-server.mtv.google.com"\n' 137 ' leftprotoport=17/1701\n' 138 ' right=%%any\n' 139 ' rightca="C=US, ST=California, L=Mountain View, ' 140 'CN=chromelab-wifi-testbed-root.mtv.google.com"\n' 141 ' rightprotoport=17/%%any\n' 142 ' auto=add\n', 143 144 'etc/ipsec.secrets' : ': RSA server.key ""\n', 145 146 IPSEC_SERVER_CERTIFICATE : site_eap_certs.server_cert_1, 147 IPSEC_CA_CERTIFICATE : site_eap_certs.ca_cert_1, 148 'etc/ipsec.d/private/server.key' : 149 site_eap_certs.server_private_key_1, 150 }, 151 } 152 153 """Implementation of an L2TP/IPSec server instance.""" 154 def __init__(self, auth_type, interface_name, address, network_prefix, 155 perform_xauth_authentication=False, 156 local_ip_is_public_ip=False): 157 self._auth_type = auth_type 158 self._chroot = network_chroot.NetworkChroot(interface_name, 159 address, network_prefix) 160 self._perform_xauth_authentication = perform_xauth_authentication 161 162 if local_ip_is_public_ip: 163 self.IPSEC_COMMON_CONFIGS[self.XL2TPD_CONFIG_FILE] = \ 164 self.IPSEC_COMMON_CONFIGS[self.XL2TPD_CONFIG_FILE].replace( 165 self.SERVER_IP_ADDRESS, address) 166 self.SERVER_IP_ADDRESS = address 167 168 169 def start_server(self): 170 """Start VPN server instance""" 171 if self._auth_type not in self.IPSEC_TYPED_CONFIGS: 172 raise RuntimeError('L2TP/IPSec type %s is not define' % 173 self._auth_type) 174 chroot = self._chroot 175 chroot.add_root_directories(self.ROOT_DIRECTORIES) 176 chroot.add_config_templates(self.IPSEC_COMMON_CONFIGS) 177 chroot.add_config_templates(self.IPSEC_TYPED_CONFIGS[self._auth_type]) 178 chroot.add_config_values({ 179 'chap-user': self.CHAP_USER, 180 'chap-secret': self.CHAP_SECRET, 181 'charon-debug-flags': 'dmn 2, mgr 2, ike 2, net 2', 182 'charon-logfile': self.IPSEC_LOGFILE, 183 'preshared-key': self.IPSEC_PRESHARED_KEY, 184 'xauth-user': self.XAUTH_USER, 185 'xauth-password': self.XAUTH_PASSWORD, 186 'xauth-stanza': self.XAUTH_SECONDARY_AUTHENTICATION_STANZA 187 if self._perform_xauth_authentication else '', 188 }) 189 chroot.add_startup_command('%s start' % self.IPSEC_COMMAND) 190 chroot.add_startup_command('%s -c /%s -C /tmp/l2tpd.control' % 191 (self.XL2TPD_COMMAND, 192 self.XL2TPD_CONFIG_FILE)) 193 self.preload_modules() 194 chroot.startup() 195 196 197 def stop_server(self): 198 """Start VPN server instance""" 199 chroot = self._chroot 200 chroot.run([self.IPSEC_COMMAND, 'stop'], ignore_status=True) 201 chroot.kill_pid_file(self.XL2TPD_PID_FILE, missing_ok=True) 202 chroot.kill_pid_file(self.PPPD_PID_FILE, missing_ok=True) 203 chroot.shutdown() 204 205 206 def get_log_contents(self): 207 """Return all logs related to the chroot.""" 208 return self._chroot.get_log_contents() 209 210 211 def preload_modules(self): 212 """Pre-load ipsec modules since they can't be loaded from chroot.""" 213 for module in self.PRELOAD_MODULES: 214 utils.system('modprobe %s' % module) 215 216 217 class OpenVPNServer(VPNServer): 218 """Implementation of an OpenVPN service.""" 219 PRELOAD_MODULES = ('tun',) 220 ROOT_DIRECTORIES = ('etc/openvpn', 'etc/ssl') 221 CA_CERTIFICATE_FILE = 'etc/openvpn/ca.crt' 222 SERVER_CERTIFICATE_FILE = 'etc/openvpn/server.crt' 223 SERVER_KEY_FILE = 'etc/openvpn/server.key' 224 DIFFIE_HELLMAN_FILE = 'etc/openvpn/diffie-hellman.pem' 225 OPENVPN_COMMAND = '/usr/sbin/openvpn' 226 OPENVPN_CONFIG_FILE = 'etc/openvpn/openvpn.conf' 227 OPENVPN_PID_FILE = 'run/openvpn.pid' 228 OPENVPN_STATUS_FILE = 'tmp/openvpn.status' 229 AUTHENTICATION_SCRIPT = 'etc/openvpn_authentication_script.sh' 230 EXPECTED_AUTHENTICATION_FILE = 'etc/openvpn_expected_authentication.txt' 231 PASSWORD = 'password' 232 USERNAME = 'username' 233 SERVER_IP_ADDRESS = '10.11.12.1' 234 CONFIGURATION = { 235 'etc/ssl/blacklist' : '', 236 CA_CERTIFICATE_FILE : site_eap_certs.ca_cert_1, 237 SERVER_CERTIFICATE_FILE : site_eap_certs.server_cert_1, 238 SERVER_KEY_FILE : site_eap_certs.server_private_key_1, 239 DIFFIE_HELLMAN_FILE : site_eap_certs.dh1024_pem_key_1, 240 AUTHENTICATION_SCRIPT : 241 '#!/bin/bash\n' 242 'diff -q $1 %(expected-authentication-file)s\n', 243 EXPECTED_AUTHENTICATION_FILE : '%(username)s\n%(password)s\n', 244 OPENVPN_CONFIG_FILE : 245 'ca /%(ca-cert)s\n' 246 'cert /%(server-cert)s\n' 247 'dev tun\n' 248 'dh /%(diffie-hellman-params-file)s\n' 249 'keepalive 10 120\n' 250 'local %(local-ip)s\n' 251 'log /var/log/openvpn.log\n' 252 'ifconfig-pool-persist /tmp/ipp.txt\n' 253 'key /%(server-key)s\n' 254 'persist-key\n' 255 'persist-tun\n' 256 'port 1194\n' 257 'proto udp\n' 258 'server 10.11.12.0 255.255.255.0\n' 259 'status /%(status-file)s\n' 260 'verb 5\n' 261 'writepid /%(pid-file)s\n' 262 '%(optional-user-verification)s\n' 263 } 264 265 def __init__(self, interface_name, address, network_prefix, 266 perform_username_authentication=False): 267 self._chroot = network_chroot.NetworkChroot(interface_name, 268 address, network_prefix) 269 self._perform_username_authentication = perform_username_authentication 270 271 272 def start_server(self): 273 """Start VPN server instance""" 274 chroot = self._chroot 275 chroot.add_root_directories(self.ROOT_DIRECTORIES) 276 # Create a configuration template from the key-value pairs. 277 chroot.add_config_templates(self.CONFIGURATION) 278 config_values = { 279 'ca-cert': self.CA_CERTIFICATE_FILE, 280 'diffie-hellman-params-file': self.DIFFIE_HELLMAN_FILE, 281 'expected-authentication-file': self.EXPECTED_AUTHENTICATION_FILE, 282 'optional-user-verification': '', 283 'password': self.PASSWORD, 284 'pid-file': self.OPENVPN_PID_FILE, 285 'server-cert': self.SERVER_CERTIFICATE_FILE, 286 'server-key': self.SERVER_KEY_FILE, 287 'status-file': self.OPENVPN_STATUS_FILE, 288 'username': self.USERNAME, 289 } 290 if self._perform_username_authentication: 291 config_values['optional-user-verification'] = ( 292 'auth-user-pass-verify /%s via-file\nscript-security 2' % 293 self.AUTHENTICATION_SCRIPT) 294 chroot.add_config_values(config_values) 295 chroot.add_startup_command('chmod 755 %s' % self.AUTHENTICATION_SCRIPT) 296 chroot.add_startup_command('%s --config /%s &' % 297 (self.OPENVPN_COMMAND, 298 self.OPENVPN_CONFIG_FILE)) 299 self.preload_modules() 300 chroot.startup() 301 302 303 def preload_modules(self): 304 """Pre-load modules since they can't be loaded from chroot.""" 305 for module in self.PRELOAD_MODULES: 306 utils.system('modprobe %s' % module) 307 308 309 def get_log_contents(self): 310 """Return all logs related to the chroot.""" 311 return self._chroot.get_log_contents() 312 313 314 def stop_server(self): 315 """Start VPN server instance""" 316 chroot = self._chroot 317 chroot.kill_pid_file(self.OPENVPN_PID_FILE, missing_ok=True) 318 chroot.shutdown() 319