vpnmaker 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +25 -0
- data/README.rdoc +91 -0
- data/Rakefile +99 -0
- data/VERSION +1 -0
- data/bin/vpnmaker +11 -0
- data/foocorp.config.yaml +24 -0
- data/lib/client.haml +13 -0
- data/lib/openssl.haml +144 -0
- data/lib/server.haml +38 -0
- data/lib/vpnmaker.rb +45 -0
- data/lib/vpnmaker/config_generator.rb +36 -0
- data/lib/vpnmaker/key_builder.rb +141 -0
- data/lib/vpnmaker/key_config.rb +9 -0
- data/lib/vpnmaker/key_db.rb +62 -0
- data/lib/vpnmaker/key_tracker.rb +158 -0
- data/lib/vpnmaker/manager.rb +55 -0
- data/vpnmaker.gemspec +99 -0
- metadata +308 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
group :development do
|
4
|
+
gem "pry"
|
5
|
+
gem 'pry-doc' #, :git => 'https://github.com/pry/pry-doc.git'
|
6
|
+
gem 'pry-rails' #, :git => 'https://github.com/rweng/pry-rails.git'
|
7
|
+
gem 'pry-nav' #, :git => 'https://github.com/nixme/pry-nav.git'
|
8
|
+
gem 'pry-syntax-hacks' #, :git => 'https://github.com/ConradIrwin/pry-syntax-hacks.git'
|
9
|
+
gem 'pry-stack_explorer' #, :git => 'https://github.com/pry/pry-stack_explorer.git'
|
10
|
+
gem 'pry-exception_explorer' #, :git => 'https://github.com/pry/pry-exception_explorer.git'
|
11
|
+
gem "rdoc", "~> 3.12"
|
12
|
+
gem "bundler" #, "~> 1.0.0"
|
13
|
+
gem "jeweler" #, "~> 1.8.3"
|
14
|
+
end
|
15
|
+
|
16
|
+
gem 'ipaddr_extensions'
|
17
|
+
#, :git => 'git://github.com/jamesotron/IPAddrExtensions.git'
|
18
|
+
|
19
|
+
gem 'haml'
|
20
|
+
gem 'trollop'
|
21
|
+
gem 'gibberish', :git => 'git://github.com/mdp/gibberish.git'
|
22
|
+
gem 'rubyzip', :git => 'git://github.com/aussiegeek/rubyzip.git'
|
23
|
+
# gem 'slim'
|
24
|
+
|
25
|
+
# gem 'slop', :git => 'git://github.com/injekt/slop.git'
|
data/README.rdoc
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
most of the code was stolen from here: http://github.com/pc/vpnmaker
|
2
|
+
i made a gem and converted it to use haml
|
3
|
+
= VPNMaker
|
4
|
+
|
5
|
+
VPNMaker takes the teetering jankiness out of setting up and administering OpenVPN.
|
6
|
+
|
7
|
+
== Key management
|
8
|
+
|
9
|
+
To set up your VPN, run:
|
10
|
+
|
11
|
+
irb -r vpnmaker
|
12
|
+
>> VPNMaker.generate('foocorp', '/root')
|
13
|
+
|
14
|
+
Which will place <tt>foocorp.vpn</tt> in <tt>/root</tt>. All of the files that OpenVPN needs will be placed in <tt>/root/foocorp.vpn/foocorp_data</tt>.
|
15
|
+
|
16
|
+
Next, you should create <tt>foocorp.config.yaml</tt> in <tt>/root/foocorp.vpn</tt>. It should look something like this:
|
17
|
+
|
18
|
+
:key_properties:
|
19
|
+
:country: US
|
20
|
+
:province: CA
|
21
|
+
:city: San Francisco
|
22
|
+
:organization: FooCorp Inc
|
23
|
+
:email: security@foocorp.com
|
24
|
+
|
25
|
+
The values in <tt>foocorp.config.yaml</tt> will be used to generate keys and OpenVPN configuration files.
|
26
|
+
|
27
|
+
Administration tasks are carried out with <tt>VPNMaker::Manager</tt>.
|
28
|
+
|
29
|
+
Creating the Certificate Authority is the first order of business. You'll want to keep its keys safe from both intruders and data loss.
|
30
|
+
|
31
|
+
>> mgr = VPNMaker::Manager.new('/root/foocorp.vpn')
|
32
|
+
>> mgr.build_ca
|
33
|
+
|
34
|
+
Behind the scenes, this will create <tt>ca.crt</tt>, <tt>ca.key</tt>, <tt>crl.pem</tt>, <tt>dh.pem</tt>, <tt>index.txt</tt> and <tt>serial</tt> in the <tt>foocorp_data</tt> directory. Respectively these are: the public certificate for the CA that every user should get; the private key for signing other certs that should be kept safe; a certificate revocation file you'll need to revoke signed certificates (e.g. after a laptop is compromised); an encryption key for the server side of the VPN connection; a file for OpenSSL to track key state that you should never need to touch; and another file that OpenSSL uses for tracking key IDs that you shouldn't have to worry about.
|
35
|
+
|
36
|
+
Now that we have a Certificate Authority, we should create a server certificate:
|
37
|
+
|
38
|
+
>> mgr.build_server
|
39
|
+
|
40
|
+
This creates <tt>server.key</tt> and <tt>server.crt</tt> in the <tt>foocorp_data</tt> directory, both of which are for distribution only to the VPN server. It also creates <tt>dh.key</tt> and <tt>ta.key</tt>. The first of these is a key for creating TLS connections on the server; the second is a key shared between both the server and clients that provides some additional security. (See the tls-auth section at http://openvpn.net/index.php/open-source/documentation/howto.html for more details.)
|
41
|
+
|
42
|
+
Next, we can create our first user:
|
43
|
+
|
44
|
+
>> mgr.create_user('joe', 'Joe Bloggs', 'joe.bloggs@foocorp.com', 'password')
|
45
|
+
>> mgr.users
|
46
|
+
=> ['joe']
|
47
|
+
>> mgr.user('joe')
|
48
|
+
=> {:user=>"joe", :revoked=>[], :email=>"joe.bloggs@foocorp.com", :name=>"Joe Bloggs", :modified=>Mon Oct 11 10:42:44 -0700 2010, :active_key=>0}
|
49
|
+
|
50
|
+
The most important thing to note here is that Joe Bloggs has no revoked keys, and that his active key is version 0. We can go ahead and give <tt>joe-0.key</tt> and <tt>joe-0.crt</tt> to Joe. (They'll be in the <tt>foocorp_data</tt> directory.)
|
51
|
+
|
52
|
+
Now say Joe loses his laptop. We need to both disable his old key and give him a new one:
|
53
|
+
|
54
|
+
>> mgr.regenerate_user('joe', 'newpassword')
|
55
|
+
|
56
|
+
This will create new keys for Joe, and update the server's <tt>crl.pem</tt> revocation file. If we check the database, we see that his <tt>active_key</tt> is now <tt>1</tt>, while <tt>0</tt> has been added to the list of revoked keys:
|
57
|
+
|
58
|
+
>> mgr.user('joe')
|
59
|
+
=> {:user=>"joe", :revoked=>[0], :email=>"joe.bloggs@foocorp.com", :name=>"Joe Bloggs", :modified=>Mon Oct 11 10:42:44 -0700 2010, :active_key=>1}
|
60
|
+
We should now go ahead and distribute <tt>joe-1.key</tt> and <tt>joe-1.crt</tt> to Joe, as well as make sure our OpenVPN servers get the latest version of the <tt>crl.pem</tt> revocation file.
|
61
|
+
|
62
|
+
When Joe leaves the company, we can do:
|
63
|
+
|
64
|
+
>> mgr.delete_user('joe')
|
65
|
+
>> mgr.user('joe')
|
66
|
+
=> {:user=>"joe", :revoked=>[0, 1], :email=>"joe.bloggs@foocorp.com", :name=>"Joe Bloggs", :modified=>Mon Oct 11 11:32:10 -0700 2010, :active_key=>1}
|
67
|
+
|
68
|
+
Which does the same revocation as in <tt>regenerate_user</tt>, but doesn't generate new keys.
|
69
|
+
|
70
|
+
== OpenVPN management
|
71
|
+
|
72
|
+
To get OpenVPN set up, you should go back and edit <tt>foocorp.config.yaml</tt>, and add the following section:
|
73
|
+
|
74
|
+
:server:
|
75
|
+
:base_ip: 10.10.10.0
|
76
|
+
:user: nouser
|
77
|
+
:group: nogroup
|
78
|
+
:root: /root/openvpn
|
79
|
+
:log: /var/log/openvpn.log
|
80
|
+
:host: foocorp.com
|
81
|
+
:port: 1194
|
82
|
+
|
83
|
+
You may want to modify some of the values. Then, head back to irb, and do something like:
|
84
|
+
|
85
|
+
>> puts mgr.config_generator.server
|
86
|
+
|
87
|
+
Which will output a config file that you can copy and paste into <tt>openvpn.conf</tt> on your server. You'll want make sure that the following files exist in <tt>/root/openvpn</tt> (or whatever your root directory is): <tt>ca.crt</tt> (so that the server can verify the validity of client certificates), <tt>dh.pem</tt> (for encryption of the connection), <tt>server.crt</tt> (the server's public key), <tt>server.key</tt> (the server's private key), <tt>ta.key</tt> (shared secret between server and clients), and <tt>crl.pem</tt> (so that the server will reject revoked certificates).
|
88
|
+
|
89
|
+
== OpenVPN client
|
90
|
+
|
91
|
+
Each client will need: <tt>user.key</tt>, <tt>user.crt</tt>, <tt>ca.crt</tt> and <tt>ta.key</tt>. Make sure to enable tls-auth = 1.
|
data/Rakefile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "vpnmaker"
|
18
|
+
gem.executables = 'vpnmaker'
|
19
|
+
gem.homepage = "http://github.com/voipscout/vpnmaker"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = %Q{Makes it easy to manage OpenVPN}
|
22
|
+
gem.description = %Q{haml templates and key tracking}
|
23
|
+
gem.email = "voipscout@gmail.com"
|
24
|
+
gem.authors = ["Voip Scout"]
|
25
|
+
# dependencies defined in Gemfile
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
# require 'rake/testtask'
|
30
|
+
# Rake::TestTask.new(:test) do |test|
|
31
|
+
# test.libs << 'lib' << 'test'
|
32
|
+
# test.pattern = 'test/**/test_*.rb'
|
33
|
+
# test.verbose = true
|
34
|
+
# end
|
35
|
+
|
36
|
+
# require 'rcov/rcovtask'
|
37
|
+
# Rcov::RcovTask.new do |test|
|
38
|
+
# test.libs << 'test'
|
39
|
+
# test.pattern = 'test/**/test_*.rb'
|
40
|
+
# test.verbose = true
|
41
|
+
# test.rcov_opts << '--exclude "gems/*"'
|
42
|
+
# end
|
43
|
+
|
44
|
+
# task :default => :test
|
45
|
+
|
46
|
+
require 'rdoc/task'
|
47
|
+
Rake::RDocTask.new do |rdoc|
|
48
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
49
|
+
|
50
|
+
rdoc.rdoc_dir = 'rdoc'
|
51
|
+
rdoc.title = "vpnmaker #{version}"
|
52
|
+
rdoc.rdoc_files.include('README*')
|
53
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
54
|
+
end
|
55
|
+
|
56
|
+
# require 'highline/import'
|
57
|
+
# require File.join(File.dirname(__FILE__), 'vpnmaker')
|
58
|
+
|
59
|
+
# def get_arg(argname, echo=true)
|
60
|
+
# return ENV[argname] if ENV[argname]
|
61
|
+
# ask("Value for #{argname}?") { |q| q.echo = false unless echo }
|
62
|
+
# end
|
63
|
+
|
64
|
+
# namespace :config do
|
65
|
+
# desc 'Generate server config'
|
66
|
+
# task :server => :environment do
|
67
|
+
# puts $manager.config_generator.server
|
68
|
+
# end
|
69
|
+
|
70
|
+
# desc 'Generate client config'
|
71
|
+
# task :client => :environment do
|
72
|
+
# username = get_arg('username')
|
73
|
+
# puts $manager.config_generator.client($manager.user(username))
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
|
77
|
+
# namespace :user do
|
78
|
+
# desc 'Create a new user'
|
79
|
+
# task :create => :environment do
|
80
|
+
# cn = get_arg('cn')
|
81
|
+
# name = get_arg('name')
|
82
|
+
# email = get_arg('email')
|
83
|
+
# password = get_arg('password', false)
|
84
|
+
# confirm_password = get_arg('confirm_password', false)
|
85
|
+
# raise ArgumentError.new("Password mismatch") unless password == confirm_password
|
86
|
+
|
87
|
+
# if password.length > 0
|
88
|
+
# $manager.create_user(cn, name, email, password)
|
89
|
+
# else
|
90
|
+
# $manager.create_user(cn, name, email)
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
|
95
|
+
# # Set up environment
|
96
|
+
# task :environment do
|
97
|
+
# vpndir = get_arg('vpndir')
|
98
|
+
# $manager = VPNMaker::Manager.new(vpndir)
|
99
|
+
# end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/bin/vpnmaker
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/vpnmaker.rb'
|
3
|
+
require 'trollop'
|
4
|
+
|
5
|
+
opts = Trollop::options do
|
6
|
+
version "vpnmaker 0.0.1 (c) Coolio"
|
7
|
+
banner "vpnmaker [options]"
|
8
|
+
opt :verbose, 'Enable verbose mode'
|
9
|
+
end
|
10
|
+
|
11
|
+
#raise Trollop::HelpNeeded if ARGV.empty?
|
data/foocorp.config.yaml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
:server:
|
2
|
+
:base_ip: 10.10.10.0
|
3
|
+
:bridgednets: # real networks to bridge via the VPN server
|
4
|
+
- 172.16.0.0
|
5
|
+
:subnets: # subnets that exist only on the VPN
|
6
|
+
- 10.10.11.0
|
7
|
+
:user: nobody
|
8
|
+
:group: nogroup
|
9
|
+
:root: /root/openvpn
|
10
|
+
:log: /var/log/openvpn.log
|
11
|
+
:host: vpn.foocorp.com
|
12
|
+
:port: 1194
|
13
|
+
|
14
|
+
:client:
|
15
|
+
:subnet: 172.16.0.0
|
16
|
+
:local_endpoint: 10.10.10.100
|
17
|
+
:remote_endpoint: 10.10.10.1
|
18
|
+
|
19
|
+
:key_properties:
|
20
|
+
:country: US
|
21
|
+
:province: CA
|
22
|
+
:city: San Francisco
|
23
|
+
:organization: FooCorp Inc
|
24
|
+
:email: sec@foocorp.com
|
data/lib/client.haml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
remote #{server[:host]} #{server[:port]} udp
|
2
|
+
persist-key
|
3
|
+
tls-client
|
4
|
+
tls-auth ta.key 1
|
5
|
+
pull
|
6
|
+
ca ca.crt
|
7
|
+
dev tun
|
8
|
+
persist-tun
|
9
|
+
cert #{user}-#{(revoked.max || - 1) + 1}.crt
|
10
|
+
nobind
|
11
|
+
key #{user}-#{(revoked.max || - 1) + 1}.key
|
12
|
+
remote-cert-tls server
|
13
|
+
:plain
|
data/lib/openssl.haml
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
HOME = .
|
2
|
+
RANDFILE = $ENV::HOME/.rnd
|
3
|
+
openssl_conf = openssl_init
|
4
|
+
|
5
|
+
[ openssl_init ]
|
6
|
+
oid_section = new_oids
|
7
|
+
engines = engine_section
|
8
|
+
|
9
|
+
[ new_oids ]
|
10
|
+
[ ca ]
|
11
|
+
default_ca = CA_default
|
12
|
+
|
13
|
+
[CA_default ]
|
14
|
+
|
15
|
+
dir = #{key_dir}
|
16
|
+
certs = $dir # Where the issued certs are kept
|
17
|
+
crl_dir = $dir # Where the issued crl are kept
|
18
|
+
database = $dir/index.txt # database index file.
|
19
|
+
new_certs_dir = $dir # default place for new certs.
|
20
|
+
|
21
|
+
certificate = $dir/ca.crt # The CA certificate
|
22
|
+
serial = $dir/serial # The current serial number
|
23
|
+
crl = $dir/crl.pem # The current CRL
|
24
|
+
private_key = $dir/ca.key # The private key
|
25
|
+
RANDFILE = $dir/.rand # private random number file
|
26
|
+
|
27
|
+
x509_extensions = usr_cert # The extentions to add to the cert
|
28
|
+
|
29
|
+
default_days = 3650 # how long to certify for
|
30
|
+
default_crl_days= 30 # how long before next CRL
|
31
|
+
default_md = md5 # which md to use.
|
32
|
+
preserve = no # keep passed DN ordering
|
33
|
+
|
34
|
+
policy = policy_anything
|
35
|
+
|
36
|
+
[ policy_match ]
|
37
|
+
countryName = match
|
38
|
+
stateOrProvinceName = match
|
39
|
+
organizationName = match
|
40
|
+
organizationalUnitName = optional
|
41
|
+
commonName = supplied
|
42
|
+
name = optional
|
43
|
+
emailAddress = optional
|
44
|
+
|
45
|
+
[ policy_anything ]
|
46
|
+
countryName = optional
|
47
|
+
stateOrProvinceName = optional
|
48
|
+
localityName = optional
|
49
|
+
organizationName = optional
|
50
|
+
organizationalUnitName = optional
|
51
|
+
commonName = supplied
|
52
|
+
name = optional
|
53
|
+
emailAddress = optional
|
54
|
+
|
55
|
+
[ req ]
|
56
|
+
default_bits = #{key_size}
|
57
|
+
default_keyfile = privkey.pem
|
58
|
+
distinguished_name = req_distinguished_name
|
59
|
+
attributes = req_attributes
|
60
|
+
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
61
|
+
|
62
|
+
string_mask = nombstr
|
63
|
+
|
64
|
+
[ req_distinguished_name ]
|
65
|
+
countryName = Country Name (2 letter code)
|
66
|
+
countryName_default = #{key_country}
|
67
|
+
countryName_min = 2
|
68
|
+
countryName_max = 2
|
69
|
+
|
70
|
+
stateOrProvinceName = State or Province Name (full name)
|
71
|
+
stateOrProvinceName_default = #{key_province}
|
72
|
+
|
73
|
+
localityName = Locality Name (eg, city)
|
74
|
+
localityName_default = #{key_city}
|
75
|
+
|
76
|
+
0.organizationName = Organization Name (eg, company)
|
77
|
+
0.organizationName_default = #{key_org}
|
78
|
+
|
79
|
+
organizationalUnitName = Organizational Unit Name (eg, section)
|
80
|
+
|
81
|
+
commonName = Common Name (eg, your name or your server\'s hostname)
|
82
|
+
commonName_max = 64
|
83
|
+
|
84
|
+
name = Name
|
85
|
+
name_max = 64
|
86
|
+
|
87
|
+
emailAddress = Email Address
|
88
|
+
emailAddress_default = #{key_email}
|
89
|
+
emailAddress_max = 40
|
90
|
+
|
91
|
+
organizationalUnitName_default = #{key_ou}
|
92
|
+
commonName_default = #{key_cn}
|
93
|
+
name_default = #{key_name}
|
94
|
+
|
95
|
+
[ req_attributes ]
|
96
|
+
challengePassword = A challenge password
|
97
|
+
challengePassword_min = 4
|
98
|
+
challengePassword_max = 20
|
99
|
+
|
100
|
+
unstructuredName = An optional company name
|
101
|
+
|
102
|
+
[ usr_cert ]
|
103
|
+
|
104
|
+
basicConstraints=CA:FALSE
|
105
|
+
nsComment = "Easy-RSA Generated Certificate"
|
106
|
+
|
107
|
+
subjectKeyIdentifier=hash
|
108
|
+
authorityKeyIdentifier=keyid,issuer:always
|
109
|
+
extendedKeyUsage=clientAuth
|
110
|
+
keyUsage = digitalSignature
|
111
|
+
|
112
|
+
[ server ]
|
113
|
+
|
114
|
+
basicConstraints=CA:FALSE
|
115
|
+
nsCertType = server
|
116
|
+
nsComment = "Easy-RSA Generated Server Certificate"
|
117
|
+
subjectKeyIdentifier=hash
|
118
|
+
authorityKeyIdentifier=keyid,issuer:always
|
119
|
+
extendedKeyUsage=serverAuth
|
120
|
+
keyUsage = digitalSignature, keyEncipherment
|
121
|
+
|
122
|
+
[ v3_req ]
|
123
|
+
|
124
|
+
basicConstraints = CA:FALSE
|
125
|
+
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
126
|
+
|
127
|
+
[ v3_ca ]
|
128
|
+
subjectKeyIdentifier=hash
|
129
|
+
|
130
|
+
authorityKeyIdentifier=keyid:always,issuer:always
|
131
|
+
basicConstraints = CA:true
|
132
|
+
|
133
|
+
[ crl_ext ]
|
134
|
+
authorityKeyIdentifier=keyid:always,issuer:always
|
135
|
+
|
136
|
+
[ engine_section ]
|
137
|
+
|
138
|
+
[ pkcs11_section ]
|
139
|
+
engine_id = pkcs11
|
140
|
+
dynamic_path = /usr/lib/engines/engine_pkcs11.so
|
141
|
+
MODULE_PATH = blub # $ENV::PKCS11_MODULE_PATH
|
142
|
+
PIN = blub # $ENV::PKCS11_PIN
|
143
|
+
init = 0
|
144
|
+
:plain
|
data/lib/server.haml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
\# Auto-generated by vpnmaker on #{gen_host} #{Time.now.to_s}
|
2
|
+
\# See http://github.com/pc/vpnmaker
|
3
|
+
mode server
|
4
|
+
tls-server
|
5
|
+
local #{host}
|
6
|
+
port #{port}
|
7
|
+
proto udp
|
8
|
+
|
9
|
+
dev tun0
|
10
|
+
server #{base_ip[:net]} #{base_ip[:mask]}
|
11
|
+
\
|
12
|
+
\# subnets.each do
|
13
|
+
- subnets.each do |net|
|
14
|
+
route #{net[:net]} #{net[:mask]}
|
15
|
+
push route #{net[:mask]} #{net[:mask]}
|
16
|
+
\
|
17
|
+
\# bridgednets.each do
|
18
|
+
- bridgednets.each do |net|
|
19
|
+
push route #{net[:net]} #{net[:mask]}
|
20
|
+
\
|
21
|
+
user #{user}
|
22
|
+
group #{group}
|
23
|
+
dh #{root}/keys/dh.pem
|
24
|
+
ca #{root}/keys/ca.crt
|
25
|
+
cert #{root}/keys/server.crt
|
26
|
+
key #{root}/keys/server.key
|
27
|
+
crl-verify #{root}/keys/crl.pem
|
28
|
+
|
29
|
+
keepalive 10 120
|
30
|
+
|
31
|
+
log #{log}
|
32
|
+
|
33
|
+
persist-tun
|
34
|
+
persist-key
|
35
|
+
|
36
|
+
tls-auth #{root}/keys/ta.key 0
|
37
|
+
client-config-dir #{root}/ccd
|
38
|
+
:plain
|