由于经常被墙,为了减少×××次数逐转到此,不定期更新。
Generate the master Certificate Authority (CA) certificate & key
In this section we will generate a master CA certificate/key, a server certificate/key, and certificates/keys for 3 separate clients.
For PKI management, we will use a set of scripts bundled with Open×××.
If you are using Linux, BSD, or a unix-like OS, open a shell and cd to the easy-rsa subdirectory of the Open××× distribution. If you installed Open××× from an RPM file, the easy-rsa directory can usually be found in /usr/share/doc/packages/openvpn or/usr/share/doc/openvpn-2.0 (it's best to copy this directory to another location such as /etc/openvpn, before any edits, so that future Open××× package upgrades won't overwrite your modifications). If you installed from a .tar.gz file, the easy-rsa directory will be in the top level directory of the expanded source tree.
If you are using Windows, open up a Command Prompt window and cd to \Program Files\Open×××\easy-rsa. Run the following batch file to copy configuration files into place (this will overwrite any preexisting vars.bat and openssl.cnf files):
init-config
Now edit the vars file (called vars.bat on Windows) and set the KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, and KEY_EMAIL parameters. Don't leave any of these parameters blank.
Next, initialize the PKI. On Linux/BSD/Unix:
. ./vars
./clean-all
./build-ca
On Windows:
vars
clean-all
build-ca
The final command (build-ca) will build the certificate authority (CA) certificate and key by invoking the interactive opensslcommand:
ai:easy-rsa # ./build-ca
Generating a 1024 bit RSA private key
............++++++
...........++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [KG]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [BISHKEK]:
Organization Name (eg, company) [Open×××-TEST]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:Open×××-CA
Email Address [me@myhost.mydomain]:
Note that in the above sequence, most queried parameters were defaulted to the values set in the varsor vars.bat files. The only parameter which must be explicitly entered is the Common Name. In the example above, I used "Open×××-CA". Generate certificate & key for serverNext, we will generate a certificate and private key for the server. On Linux/BSD/Unix: ./build-key-server server On Windows: build-key-server server As in the previous step, most parameters can be defaulted. When the Common Name is queried, enter "server". Two other queries require positive responses, "Sign the certificate? [y/n]" and "1 out of 1 certificate requests certified, commit? [y/n]". Generate certificates & keys for 3 clientsGenerating client certificates is very similar to the previous step. On Linux/BSD/Unix: ./build-key client1 On Windows: build-key client1 If you would like to password-protect your client keys, substitute the build-key-pass script. Remember that for each client, make sure to type the appropriate Common Name when prompted, i.e. "client1", "client2", or "client3". Always use a unique common name for each client. Generate Diffie Hellman parametersDiffie Hellman parameters must be generated for the Open××× server. On Linux/BSD/Unix: ./build-dh On Windows: build-dh Output: |
ai:easy-rsa # ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
.................+...........................................
...................+.............+.................+.........
......................................
Key FilesNow we will find our newly-generated keys and certificates in the keys subdirectory. Here is an explanation of the relevant files:
The final step in the key generation process is to copy all files to the machines which need them, taking care to copy secret files over a secure channel. Now wait, you may say. Shouldn't it be possible to set up the PKI without a pre-existing secure channel? The answer is ostensibly yes. In the example above, for the sake of brevity, we generated all private keys in the same place. With a bit more effort, we could have done this differently. For example, instead of generating the client certificate and keys on the server, we could have had the client generate its own private key locally, and then submit a Certificate Signing Request (CSR) to the key-signing machine. In turn, the key-signing machine could have processed the CSR and returned a signed certificate to the client. This could have been done without ever requiring that a secret .key file leave the hard drive of the machine on which it was generated. Creating configuration files for server and clientsGetting the sample config filesIt's best to use the Open××× sample configuration files as a starting point for your own configuration. These files can also be found in
Note that on Linux, BSD, or unix-like OSes, the sample configuration files are named server.conf andclient.conf. On Windows they are named server.ovpn and client.ovpn. Editing the server configuration fileThe sample server configuration file is an ideal starting point for an Open××× server configuration. It will create a ××× using a virtual TUN network interface (for routing), will listen for client connections on UDP port 1194 (Open×××'s official port number), and distribute virtual addresses to connecting clients from the 10.8.0.0/24 subnet. Before you use the sample configuration file, you should first edit the ca, cert, key, and dh parameters to point to the files you generated in the PKI section above. At this point, the server configuration file is usable, however you still might want to customize it further:
If you want to run multiple Open××× instances on the same machine, each using a different configuration file, it is possible if you:
Editing the client configuration filesThe sample client configuration file (client.conf on Linux/BSD/Unix or client.ovpn on Windows) mirrors the default directives set in the sample server configuration file.
Starting up the ××× and testing for initial connectivityStarting the serverFirst, make sure the Open××× server will be accessible from the internet. That means:
Next, make sure that the TUN/TAP interface is not firewalled. To simplify troubleshooting, it's best to initially start the Open××× server from the command line (or right-click on the .ovpn file on Windows), rather than start it as a daemon or service: openvpn [server config file] A normal server startup should look like this (output will vary across platforms): |
Sun Feb 6 20:46:38 2005 Open××× 2.0_rc12 i686-suse-linux [SSL] [LZO] [EPOLL] built on Feb 5 2005
Sun Feb 6 20:46:38 2005 Diffie-Hellman initialized with 1024 bit key
Sun Feb 6 20:46:38 2005 TLS-Auth MTU parms [ L:1542 D:138 EF:38 EB:0 ET:0 EL:0 ]
Sun Feb 6 20:46:38 2005 TUN/TAP device tun1 opened
Sun Feb 6 20:46:38 2005 /sbin/ifconfig tun1 10.8.0.1 pointopoint 10.8.0.2 mtu 1500
Sun Feb 6 20:46:38 2005 /sbin/route add -net 10.8.0.0 netmask 255.255.255.0 gw 10.8.0.2
Sun Feb 6 20:46:38 2005 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:23 ET:0 EL:0 AF:3/1 ]
Sun Feb 6 20:46:38 2005 UDPv4 link local (bound): [undef]:1194
Sun Feb 6 20:46:38 2005 UDPv4 link remote: [undef]
Sun Feb 6 20:46:38 2005 MULTI: multi_init called, r=256 v=256
Sun Feb 6 20:46:38 2005 IFCONFIG POOL: base=10.8.0.4 size=62
Sun Feb 6 20:46:38 2005 IFCONFIG POOL LIST
Sun Feb 6 20:46:38 2005 Initialization Sequence Completed
Starting the clientAs in the server configuration, it's best to initially start the Open××× server from the command line (or on Windows, by right-clicking on the client.ovpn file), rather than start it as a daemon or service: openvpn [client config file] A normal client startup on Windows will look similar to the server output above, and should end with theInitialization Sequence Completed message. Now, try a ping across the ××× from the client. If you are using routing (i.e. dev tun in the server config file), try: ping 10.8.0.1 If you are using bridging (i.e. dev tap in the server config file), try to ping the IP address of a machine on the server's ethernet subnet. If the ping succeeds, congratulations! You now have a functioning ×××. TroubleshootingIf the ping failed or the Open××× client initialization failed to complete, here is a checklist of common symptoms and their solutions:
See the FAQ for additional troubleshooting information. Configuring Open××× to run automatically on system startupThe lack of standards in this area means that most OSes have a different way of configuring daemons/services for autostart on boot. The best way to have this functionality configured by default is to install Open××× as a package, such as via RPM on Linux or using the Windows installer. LinuxIf you install Open××× via an RPM package on Linux, the installer will set up an initscript. When executed, the initscript will scan for .conf configuration files in /etc/openvpn, and if found, will start up a separate Open××× daemon for each file. WindowsThe Windows installer will set up a Service Wrapper, but leave it turned off by default. To activate it, go to Control Panel / Administrative Tools / Services, select the Open××× service, right-click on properties, and set the Startup Type to Automatic. This will configure the service for automatic start on the next reboot. When started, the Open××× Service Wrapper will scan the \Program Files\Open×××\config folder for.ovpn configuration files, starting a separate Open××× process on each file. Controlling a running Open××× processRunning on Linux/BSD/UnixOpen××× accepts several signals:
Use the writepid directive to write the Open××× daemon's PID to a file, so that you know where to send the signal (if you are starting openvpn with an initscript, the script may already be passing a --writepid directive on the openvpn command line). Running on Windows as a GUISee the Open××× GUI page. Running in a Windows command prompt windowOn Windows, you can start Open××× by right clicking on an Open××× configuration file (.ovpn file) and selecting "Start Open××× on this config file". Once running in this fashion, several keyboard commands are available:
Running as a Windows ServiceWhen Open××× is started as a service on Windows, the only way to control it is:
Modifying a live server configurationWhile most configuration changes require you to restart the server, there are two directives in particular which refer to files which can be dynamically updated on-the-fly, and which will take immediate effect on the server without needing to restart the server process. client-config-dir -- This directive sets a client configuration directory, which the Open××× server will scan on every incoming connection, searching for a client-specific configuration file (see the the manual page for more information). Files in this directory can be updated on-the-fly, without restarting the server. Note that changes in this directory will only take effect for new connections, not existing connections. If you would like a client-specific configuration file change to take immediate effect on a currently connected client (or one which has disconnected, but where the server has not timed-out its instance object), kill the client instance object by using the management interface (described below). This will cause the client to reconnect and use the new client-config-dir file. crl-verify -- This directive names a Certificate Revocation List file, described below in the Revoking Certificates section. The CRL file can be modified on the fly, and changes will take effect immediately for new connections, or existing connections which are renegotiating their SSL/TLS channel (occurs once per hour by default). If you would like to kill a currently connected client whose certificate has just been added to the CRL, use the management interface (described below). Status FileThe default server.conf file has a line status openvpn-status.log which will output a list of current client connections to the file openvpn-status.log once per minute. Using the management interfaceThe Open××× management interface allows a great deal of control over a running Open××× process. You can use the management interface directly, by telneting to the management interface port, or indirectly by using an Open××× GUI which itself connects to the management interface. To enable the management interface on either an Open××× server or client, add this to the configuration file: management localhost 7505 This tells Open××× to listen on TCP port 7505 for management interface clients (port 7505 is an arbitrary choice -- you can use any free port). Once Open××× is running, you can connect to the management interface using a telnet client. For example: |
ai:~ # telnet localhost 7505
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
>INFO:Open××× Management Interface Version 1 -- type 'help' for more info
help
Management Interface for Open××× 2.0_rc14 i686-suse-linux [SSL] [LZO] [EPOLL] built on Feb 15 2005
Commands:
echo [on|off] [N|all] : Like log, but only show messages in echo buffer.
exit|quit : Close management session.
help : Print this message.
hold [on|off|release] : Set/show hold flag to on/off state, or
release current hold and start tunnel.
kill cn : Kill the client instance(s) having common name cn.
kill IP:port : Kill the client instance connecting from IP:port.
log [on|off] [N|all] : Turn on/off realtime log display
+ show last N lines or 'all' for entire history.
mute [n] : Set log mute level to n, or show level if n is absent.
net : (Windows only) Show network info and routing table.
password type p : Enter password p for a queried Open××× password.
signal s : Send signal s to daemon,
s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.
state [on|off] [N|all] : Like log, but show state history.
status [n] : Show current daemon status info using format #n.
test n : Produce n lines of output for testing/debugging.
username type u : Enter username u for a queried Open××× username.
verb [n] : Set log verbosity level to n, or show if n is absent.
version : Show current version number.
END
exit
Connection closed by foreign host.
ai:~ #
For more information, see the Open××× Management Interface Documentation. Expanding the scope of the ××× to include additional machines on either the client or server subnet.Including multiple machines on the server side when using a routed ××× (dev tun)Once the ××× is operational in a point-to-point capacity between client and server, it may be desirable to expand the scope of the ××× so that clients can reach multiple machines on the server network, rather than only the server machine itself. For the purpose of this example, we will assume that the server-side LAN uses a subnet of 10.66.0.0/24and the ××× IP address pool uses 10.8.0.0/24 as cited in the server directive in the Open××× server configuration file. First, you must advertise the 10.66.0.0/24 subnet to ××× clients as being accessible through the ×××. This can easily be done with the following server-side config file directive: push "route 10.66.0.0 255.255.255.0" Next, you must set up a route on the server-side LAN gateway to route the ××× client subnet (10.8.0.0/24) to the Open××× server (this is only necessary if the Open××× server and the LAN gateway are different machines). Make sure that you've enabled IP and TUN/TAP forwarding on the Open××× server machine. Including multiple machines on the server side when using a bridged ××× (dev tap)One of the benefits of using ethernet bridging is that you get this for free without needing any additional configuration. Including multiple machines on the client side when using a routed ××× (dev tun)In a typical road-warrior or remote access scenario, the client machine connects to the ××× as a single machine. But suppose the client machine is a gateway for a local LAN (such as a home office), and you would like each machine on the client LAN to be able to route through the ×××. For this example, we will assume that the client LAN is using the 192.168.4.0/24 subnet, and that the ××× client is using a certificate with a common name of client2. Our goal is to set up the ××× so that any machine on the client LAN can communicate with any machine on the server LAN through the ×××. Before setup, there are some basic prerequisites which must be followed:
First, make sure that IP and TUN/TAP forwarding is enabled on the client machine. Next, we will deal with the necessary configuration changes on the server side. If the server configuration file does not currently reference a client configuration directory, add one now: client-config-dir ccd In the above directive, ccd should be the name of a directory which has been pre-created in the default directory where the Open××× server daemon runs. On Linux this tends to be /etc/openvpn and on Windows it is usually \Program Files\Open×××\config. When a new client connects to the Open××× server, the daemon will check this directory for a file which matches the common name of the connecting client. If a matching file is found, it will be read and processed for additional configuration file directives to be applied to the named client. The next step is to create a file called client2 in the ccd directory. This file should contain the line: iroute 192.168.4.0 255.255.255.0 This will tell the Open××× server that the 192.168.4.0/24 subnet should be routed to client2. Next, add the following line to the main server config file (not the ccd/client2 file): route 192.168.4.0 255.255.255.0 Why the redundant route and iroute statements, you might ask? The reason is that route controls the routing from the kernel to the Open××× server (via the TUN interface) while iroute controls the routing from the Open××× server to the remote clients. Both are necessary. Next, ask yourself if you would like to allow network traffic between client2's subnet (192.168.4.0/24) and other clients of the Open××× server. If so, add the following to the server config file. client-to-client This will cause the Open××× server to advertise client2's subnet to other connecting clients. The last step, and one that is often forgotten, is to add a route to the server's LAN gateway which directs 192.168.4.0/24 to the Open××× server box (you won't need this if the Open××× server box isthe gateway for the server LAN). Suppose you were missing this step and you tried to ping a machine (not the Open××× server itself) on the server LAN from 192.168.4.8? The outgoing ping would probably reach the machine, but then it wouldn't know how to route the ping reply, because it would have no idea how to reach 192.168.4.0/24. The rule of thumb to use is that when routing entire LANs through the ××× (when the ××× server is not the same machine as the LAN gateway), make sure that the gateway for the LAN routes all ××× subnets to the ××× server machine. Similarly, if the client machine running Open××× is not also the gateway for the client LAN, then the gateway for the client LAN must have a route which directs all subnets which should be reachable through the ××× to the Open××× client machine. Including multiple machines on the client side when using a bridged ××× (dev tap)This requires a more complex setup (maybe not more complex in practice, but more complicated to explain in detail):
Pushing DHCP options to clientsThe Open××× server can push DHCP options such as DNS and WINS server addresses to clients (some caveats to be aware of). Windows clients can accept pushed DHCP options natively, while non-Windows clients can accept them by using a client-side up script which parses the foreign_option_nenvironmental variable list. See the man page or openvpn-users mailing list archive for non-Windowsforeign_option_n documentation and script examples. For example, suppose you would like connecting clients to use an internal DNS server at 10.66.0.4 or 10.66.0.5 and a WINS server at 10.66.0.8. Add this to the Open××× server configuration: push "dhcp-option DNS 10.66.0.4" To test this feature on Windows, run the following from a command prompt window after the machine has connected to an Open××× server: ipconfig /all The entry for the TAP-Win32 adapter should show the DHCP options which were pushed by the server. Configuring client-specific rules and access policiesSuppose we are setting up a company ×××, and we would like to establish separate access policies for 3 different classes of users:
The basic approach we will take is (a) segregate each user class into its own virtual IP address range, and (b) control access to machines by setting up firewall rules which key off the client's virtual IP address. In our example, suppose that we have a variable number of employees, but only one system administrator, and two contractors. Our IP allocation approach will be to put all employees into an IP address pool, and then allocate fixed IP addresses for the system administrator and contractors. Note that one of the prerequisites of this example is that you have a software firewall running on the Open××× server machine which gives you the ability to define specific firewall rules. For our example, we will assume the firewall is Linux iptables. First, let's create a virtual IP address map according to user class:
Next, let's translate this map into an Open××× server configuration. First of all, make sure you've followed the steps above for making the 10.66.4.0/24 subnet available to all clients (while we will configure routing to allow client access to the entire 10.66.4.0/24 subnet, we will then impose access restrictions using firewall rules to implement the above policy table). First, define a static unit number for our tun interface, so that we will be able to refer to it later in our firewall rules: dev tun0 In the server configuration file, define the Employee IP address pool: server 10.8.0.0 255.255.255.0 Add routes for the System Administrator and Contractor IP ranges: route 10.8.1.0 255.255.255.0 Because we will be assigning fixed IP addresses for specific System Administrators and Contractors, we will use a client configuration directory: client-config-dir ccd Now place special configuration files in the ccd subdirectory to define the fixed IP address for each non-Employee ××× client. ccd/sysadmin1ifconfig-push 10.8.1.1 10.8.1.2 ccd/contractor1ifconfig-push 10.8.2.1 10.8.2.2 ccd/contractor2ifconfig-push 10.8.2.5 10.8.2.6 Each pair of ifconfig-push addresses represent the virtual client and server IP endpoints. They must be taken from successive /30 subnets in order to be compatible with Windows clients and the TAP-Win32 driver. Specifically, the last octet in the IP address of each endpoint pair must be taken from this set: |
[ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18]
[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38]
[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58]
[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78]
[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98]
[101,102] [105,106] [109,110] [113,114] [117,118]
[121,122] [125,126] [129,130] [133,134] [137,138]
[141,142] [145,146] [149,150] [153,154] [157,158]
[161,162] [165,166] [169,170] [173,174] [177,178]
[181,182] [185,186] [189,190] [193,194] [197,198]
[201,202] [205,206] [209,210] [213,214] [217,218]
[221,222] [225,226] [229,230] [233,234] [237,238]
[241,242] [245,246] [249,250] [253,254]
This completes the Open××× configuration. The final step is to add firewall rules to finalize the access policy. For this example, we will use firewall rules in the Linux iptables syntax: |
# Employee rule
iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -d 10.66.4.4 -j ACCEPT
# Sysadmin rule
iptables -A FORWARD -i tun0 -s 10.8.1.0/24 -d 10.66.4.0/24 -j ACCEPT
# Contractor rule
iptables -A FORWARD -i tun0 -s 10.8.2.0/24 -d 10.66.4.12 -j ACCEPT
Using alternative authentication methodsOpen××× 2.0 includes a feature that allows the Open××× server to securely obtain a username and password from a connecting client, and to use that information as a basis for authenticating the client. To use this authentication method, first add the auth-user-pass directive to the client configuration. It will direct the Open××× client to query the user for a username/password, passing it on to the server over the secure TLS channel. Next, configure the server to use an authentication plugin, which may be a script, shared object, or DLL. The Open××× server will call the plugin every time a ××× client tries to connect, passing it the username/password entered on the client. The authentication plugin can control whether or not the Open××× server allows the client to connect by returning a failure (1) or success (0) value. Using Script PluginsScript plugins can be used by adding the auth-user-pass-verify directive to the server-side configuration file. For example: auth-user-pass-verify via-file will use the perl script to authenticate the username/password of connecting clients. See the description of auth-user-pass-verify in the manual page for more information. The script is included in the Open××× source file distribution in the sample-scriptssubdirectory. It will authenticate users on a Linux server using a PAM authentication module, which could in turn implement shadow password, RADIUS, or LDAP authentication. is primarily intended for demonstration purposes. For real-world PAM authentication, use the openvpn-auth-pamshared object plugin described below. Using Shared Object or DLL PluginsShared object or DLL plugins are usually compiled C modules which are loaded by the Open××× server at run time. For example if you are using an RPM-based Open××× package on Linux, the openvpn-auth-pam plugin should be already built. To use it, add this to the server-side config file: |
plugin /usr/share/openvpn/plugin/lib/ login
This will tell the Open××× server to validate the username/password entered by clients using the loginPAM module. For real-world production use, it's better to use the openvpn-auth-pam plugin, because it has several advantages over the script:
If you would like more information on developing your own plugins for use with Open×××, see theREADME files in the plugin subdirectory of the Open××× source distribution. To build the openvpn-auth-pam plugin on Linux, cd to the plugin/auth-pam directory in the Open××× source distribution and run make. Using username/password authentication as the only form of client authenticationBy default, using auth-user-pass-verify or a username/password-checking plugin on the server will enable dual authentication, requiring that both client-certificate and username/password authentication succeed in order for the client to be authenticated. While it is discouraged from a security perspective, it is also possible to disable the use of client certificates, and force username/password authentication only. On the server: client-cert-not-required Such configurations should usually also set: username-as-common-name which will tell the server to use the username for indexing purposes as it would use the Common Name of a client which was authenticating via a client certificate. Note that client-cert-not-required will not obviate the need for a server certificate, so a client connecting to a server which uses client-cert-not-required may remove the cert and key directives from the client configuration file, but not the ca directive, because it is necessary for the client to verify the server certificate. How to add dual-factor authentication to an Open××× configuration using client-side smart cardsAlso see Article: The Open××× Smartcard HOWTO
About dual-factor authenticationDual-factor authentication is a method of authentication that combines two elements: something you have and something you know. Something you have should be a device that cannot be duplicated; such a device can be a cryptographic token that contains a private secret key. This private key is generated inside the device and never leaves it. If a user possessing this token attempts to access protected services on a remote network, the authorization process which grants or denies network access can establish, with a high degree of certainty, that the user seeking access is in physical possession of a known, certified token. Something you know can be a password presented to the cryptographic device. Without presenting the proper password you cannot access the private secret key. Another feature of cryptographic devices is to prohibit the use of the private secret key if the wrong password had been presented more than an allowed number of times. This behavior ensures that if a user lost his device, it would be infeasible for another person to use it. Cryptographic devices are commonly called "smart cards" or "tokens", and are used in conjunction with a PKI (Public Key Infrastructure). The ××× server can examine a X.509 certificate and verify that the user holds the corresponding private secret key. Since the device cannot be duplicated and requires a valid password, the server is able to authenticate the user with a high degree of confidence. Dual-factor authentication is much stronger than password-based authentication, because in the worst-case scenario, only one person at a time can use the cryptographic token. Passwords can be guessed and can be exposed to other users, so in the worst-case scenario an infinite number of people could attempt to gain unauthorized access when resources are protected using password-only authentication. If you store the secret private key in a file, the key is usually encrypted by a password. The problem with this approach is that the encrypted key is exposed to decryption attacks or spyware/malware running on the client machine. Unlike when using a cryptographic device, the file cannot erase itself automatically after several failed decryption attempts. What is PKCS#11?This standard specifies an API, called Cryptoki, to devices which hold cryptographic information and perform cryptographic functions. Cryptoki, pronounced "crypto-key" and short for cryptographic token interface, follows a simple object-based approach, addressing the goals of technology independence (any kind of device) and resource sharing (multiple applications accessing multiple devices), presenting to applications a common, logical view of the device called a cryptographic token. Source: RSA Security Inc. http:///rsalabs/pkcs/pkcs-11. To summarize, PKCS#11 is a standard that can be used by application software to access cryptographic tokens such as smart cards and other devices. Most device vendors provide a library that implements the PKCS#11 provider interface -- this library can be used by applications in order to access these devices. PKCS#11 is a cross-platform, vendor-independent free standard. Finding PKCS#11 provider libraryThe first thing you need to do is to find the provider library, it should be installed with the device drivers. Each vendor has its own library. For example, the OpenSC PKCS#11 provider is located at /usr/lib/pkcs11/ on Unix or at opensc-pkcs11.dll on Windows. How to configure cryptographic tokenYou should follow an enrollment procedure:
A configured token is a token that has a private key object and a certificate object, where both share the same id and label attributes. A simple enrollment utility is Easy-RSA 2.0 which is part of Open××× 2.1 series. Follow the instructions specified in the README file, and then use the pkitool in order to enroll. Initialize a token using the following command: |
$ ./pkitool --pkcs11-slots /usr/lib/pkcs11/
$ ./pkitool --pkcs11-init /usr/lib/pkcs11/
Enroll a certificate using the following command: |
$ ./pkitool --pkcs11 /usr/lib/pkcs11/ client1
$ openvpn --show-pkcs11-ids /usr/lib/pkcs11/
The following objects are available for use.
Each object shown below may be used as parameter to
--pkcs11-id option please remember to use single quote mark.
Certificate
DN: /CN=User1
Serial: 490B82C4000000000075
Serialized id: aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
This command assumes that the ××× subnet is 10.8.0.0/24 (taken from the server directive in the Open××× server configuration) and that the local ethernet interface is eth0. When redirect-gateway is used, Open××× clients will route DNS queries through the ×××, and the ××× server will need handle them. This can be accomplished by pushing a DNS server address to connecting clients which will replace their normal DNS server settings during the time that the ××× is active. For example: push "dhcp-option DNS 10.8.0.1" will configure Windows clients (or non-Windows clients with some extra server-side scripting) to use 10.8.0.1 as their DNS server. Any address which is reachable from clients may be used as the DNS server address. CaveatsRedirecting all network traffic through the ××× is not entirely a problem-free proposition. Here are some typical gotchas to be aware of:
For more information on the mechanics of the redirect-gateway directive, see the manual page. Running an Open××× server on a dynamic IP addressWhile Open××× clients can easily access the server via a dynamic IP address without any special configuration, things get more interesting when the server itself is on a dynamic address. While Open××× has no trouble handling the situation of a dynamic server, some extra configuration is required. The first step is to get a dynamic DNS address which can be configured to "follow" the server every time the server's IP address changes. There are several dynamic DNS service providers available, such as. The next step is to set up a mechanism so that every time the server's IP address changes, the dynamic DNS name will be quickly updated with the new IP address, allowing clients to find the server at its new IP address. There are two basic ways to accomplish this:
The Open××× client by default will sense when the server's IP address has changed, if the client configuration is using a remote directive which references a dynamic DNS name. The usual chain of events is that (a) the Open××× client fails to receive timely keepalive messages from the server's old IP address, triggering a restart, and (b) the restart causes the DNS name in the remote directive to be re-resolved, allowing the client to reconnect to the server at its new IP address. More information can be found in the FAQ. Connecting to an Open××× server via an HTTP proxy.Open××× supports connections through an HTTP proxy, with the following authentication modes:
First of all, HTTP proxy usage requires that you use TCP as the tunnel carrier protocol. So add the following to both client and server configurations: proto tcp Make sure that any proto udp lines in the config files are deleted. Next, add the http-proxy directive to the client configuration file (see the manual page for a full description of this directive). For example, suppose you have an HTTP proxy server on the client LAN at 192.168.4.1, which is listening for connections on port 1080. Add this to the client config: http-proxy 192.168.4.1 1080 Suppose the HTTP proxy requires Basic authentication: http-proxy 192.168.4.1 1080 stdin basic Suppose the HTTP proxy requires NTLM authentication: http-proxy 192.168.4.1 1080 stdin ntlm The two authentication examples above will cause Open××× to prompt for a username/password from standard input. If you would instead like to place these credentials in a file, replace stdin with a filename, and place the username on line 1 of this file and the password on line 2. Connecting to a Samba share over Open×××This example is intended show how Open××× clients can connect to a Samba share over a routed dev tun tunnel. If you are ethernet bridging (dev tap), you probably don't need to follow these instructions, as Open××× clients should see server-side machines in their network neighborhood. For this example, we will assume that:
If the Samba and Open××× servers are running on different machines, make sure you've followed the section on expanding the scope of the ××× to include additional machines. Next, edit your Samba configuration file (smb.conf). Make sure the hosts allow directive will permit Open××× clients coming from the 10.8.0.0/24 subnet to connect. For example: hosts allow = 10.66.0.0/24 10.8.0.0/24 127.0.0.1 If you are running the Samba and Open××× servers on the same machine, you may want to edit theinterfaces directive in the smb.conf file to also listen on the TUN interface subnet of 10.8.0.0/24: interfaces = 10.66.0.0/24 10.8.0.0/24 If you are running the Samba and Open××× servers on the same machine, connect from an Open××× client to a Samba share using the folder name: \\10.8.0.1\\sharename If the Samba and Open××× servers are on different machines, use folder name: \\10.66.0.4\sharename For example, from a command prompt window: net use z: \\10.66.0.4\sharename /USER:myusername Implementing a load-balancing/failover configurationClientThe Open××× client configuration can refer to multiple servers for load balancing and failover. For example: remote server1.mydomain will direct the Open××× client to attempt a connection with server1, server2, and server3 in that order. If an existing connection is broken, the Open××× client will retry the most recently connected server, and if that fails, will move on to the next server in the list. You can also direct the Open××× client to randomize its server list on startup, so that the client load will be probabilistically spread across the server pool. remote-random If you would also like DNS resolution failures to cause the Open××× client to move to the next server in the list, add the following: resolv-retry 60 The 60 parameter tells the Open××× client to try resolving each remote DNS name for 60 seconds before moving on to the next server in the list. The server list can also refer to multiple Open××× server daemons running on the same machine, each listening for connections on a different port, for example: remote smp-server1.mydomain 8000 If your servers are multi-processor machines, running multiple Open××× daemons on each server can be advantageous from a performance standpoint. Open××× also supports the remote directive referring to a DNS name which has multiple A records in the zone configuration for the domain. In this case, the Open××× client will randomly choose one of the Arecords every time the domain is resolved. ServerThe simplest approach to a load-balanced/failover configuration on the server is to use equivalent configuration files on each server in the cluster, except use a different virtual IP address pool for each server. For example: server1 server 10.8.0.0 255.255.255.0 server2 server 10.8.1.0 255.255.255.0 server3 server 10.8.2.0 255.255.255.0 Hardening Open××× SecurityOne of the often-repeated maxims of network security is that one should never place so much trust in a single security component that its failure causes a catastrophic security breach. Open××× provides several mechanisms to add additional security layers to hedge against such an outcome. tls-authThe tls-auth directive adds an additional HMAC signature to all SSL/TLS handshake packets for integrity verification. Any UDP packet not bearing the correct HMAC signature can be dropped without further processing. The tls-auth HMAC signature provides an additional level of security above and beyond that provided by SSL/TLS. It can protect against:
Using tls-auth requires that you generate a shared-secret key that is used in addition to the standard RSA certificate/key: openvpn --genkey --secret ta.key This command will generate an Open××× static key and write it to the file ta.key. This key should be copied over a pre-existing secure channel to the server and all client machines. It can be placed in the same directory as the RSA .key and .crt files. In the server configuration, add: tls-auth ta.key 0 In the client configuration, add: tls-auth ta.key 1 proto udpWhile Open××× allows either the TCP or UDP protocol to be used as the ××× carrier connection, the UDP protocol will provide better protection against DoS attacks and port scanning than TCP: proto udp user/group (non-Windows only)Open××× has been very carefully designed to allow root privileges to be dropped after initialization, and this feature should always be used on Linux/BSD/Solaris. Without root privileges, a running Open××× server daemon provides a far less enticing target to an attacker. user nobody Unprivileged mode (Linux only)On Linux Open××× can be run completely unprivileged. This configuration is a little more complex, but provides best security. In order to work with this configuration, Open××× must be configured to use iproute interface, this is done by specifying --enable-iproute2 to configure script. sudo package should also be available on your system. This configuration uses the Linux ability to change the permission of a tun device, so that unprivileged user may access it. It also uses sudo in order to execute iproute so that interface properties and routing table may be modified. Open××× configuration:
#!/bin/sh Execute visudo, and add the followings to allow user 'user1' to execute /sbin/ip: You can also enable a group of users with the following command:user1 ALL=(ALL) NOPASSWD: /sbin/ip %users ALL=(ALL) NOPASSWD: /sbin/ip
Please note that you must select constant X and specify tun or tap not both.dev tunX/tapX
openvpn --mktun --dev tunX --type tun --user user1 --group users Run Open××× in the context of the unprivileged user. Further security constraints may be added by examining the parameters at the /usr/local/sbin/unpriv-ip script. chroot (non-Windows only)The chroot directive allows you to lock the Open××× daemon into a so-called chroot jail, where the daemon would not be able to access any part of the host system's filesystem except for the specific directory given as a parameter to the directive. For example, chroot jail would cause the Open××× daemon to cd into the jail subdirectory on initialization, and would then reorient its root filesystem to this directory so that it would be impossible thereafter for the daemon to access any files outside of jail and its subdirectory tree. This is important from a security perspective, because even if an attacker were able to compromise the server with a code insertion exploit, the exploit would be locked out of most of the server's filesystem. Caveats: because chroot reorients the filesystem (from the perspective of the daemon only), it is necessary to place any files which Open××× might need after initialization in the jail directory, such as:
Larger RSA keysThe RSA key size is controlled by the KEY_SIZE variable in the easy-rsa/vars file, which must be set before any keys are generated. Currently set to 1024 by default, this value can reasonably be increased to 2048 with no negative impact on ××× tunnel performance, except for a slightly slower SSL/TLS renegotiation handshake which occurs once per client per hour, and a much slower one-time Diffie Hellman parameters generation process using the easy-rsa/build-dh script. Larger symmetric keysBy default Open××× uses Blowfish, a 128 bit symmetrical cipher. Open××× automatically supports any cipher which is supported by the OpenSSL library, and as such can support ciphers which use large key sizes. For example, the 256-bit version of AES (Advanced Encryption Standard) can be used by adding the following to both server and client configuration files: cipher AES-256-CBC Keep the root key (ca.key) on a standalone machine without a network connectionOne of the security benefits of using an X509 PKI (as Open××× does) is that the root CA key (ca.key) need not be present on the Open××× server machine. In a high security environment, you might want to specially designate a machine for key signing purposes, keep the machine well-protected physically, and disconnect it from all networks. Floppy disks can be used to move key files back and forth, as necessary. Such measures make it extremely difficult for an attacker to steal the root key, short of physical theft of the key signing machine. Revoking CertificatesRevoking a certificate means to invalidate a previously signed certificate so that it can no longer be used for authentication purposes. Typical reasons for wanting to revoke a certificate include:
ExampleAs an example, we will revoke the client2 certificate, which we generated above in the "key generation" section of the HOWTO. First open up a shell or command prompt window and cd to the easy-rsa directory as you did in the "key generation" section above. On Linux/BSD/Unix: . ./vars On Windows: vars You should see output similar to this: |
Using configuration from /root/openvpn/20/openvpn/tmp/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
Revoking Certificate 04.
Data Base Updated
Using configuration from /root/openvpn/20/openvpn/tmp/easy-rsa/openssl.cnf
DEBUG[load_index]: unique_subject = "yes"
client2.crt: /C=KG/ST=NA/O=Open×××-TEST/CN=client2/emailAddress=me@myhost.mydomain
error 23 at 0 depth lookup:certificate revoked
Note the "error 23" in the last line. That is what you want to see, as it indicates that a certificate verification of the revoked certificate failed. The revoke-full script will generate a CRL (certificate revocation list) file called crl.pem in the keyssubdirectory. The file should be copied to a directory where the Open××× server can access it, then CRL verification should be enabled in the server configuration: crl-verify crl.pem Now all connecting clients will have their client certificates verified against the CRL, and any positive match will result in the connection being dropped. CRL Notes
Important Note on possible "Man-in-the-Middle" attack if clients do not verify the certificate of the server they are connecting to.To avoid a possible Man-in-the-Middle attack where an authorized client tries to connect to another client by impersonating the server, make sure to enforce some kind of server certificate verification by clients. There are currently five different ways of accomplishing this, listed in the order of preference:
|
















