Attempt to get vpn to work with mutliple clients
diff --git a/xos/configurations/common/Dockerfile.common b/xos/configurations/common/Dockerfile.common
index 3653632..a6a72c5 100644
--- a/xos/configurations/common/Dockerfile.common
+++ b/xos/configurations/common/Dockerfile.common
@@ -140,6 +140,9 @@
RUN /opt/openvpn/clean-all
RUN /opt/openvpn/build-ca --batch
RUN /opt/openvpn/build-key-server --batch server
+RUN /opt/openvpn/build-dh
+RUN chmod 777 /opt/openvpn/keys/server.key
+RUN chmod 777 /opt/openvpn/keys/dh2048.pem
EXPOSE 8000
diff --git a/xos/services/vpn/admin.py b/xos/services/vpn/admin.py
index 53ec31d..617d19b 100644
--- a/xos/services/vpn/admin.py
+++ b/xos/services/vpn/admin.py
@@ -54,12 +54,11 @@
"""
creator = forms.ModelChoiceField(queryset=User.objects.all())
- server_address = forms.GenericIPAddressField(
- protocol='IPv4', required=True)
- client_address = forms.GenericIPAddressField(
- protocol='IPv4', required=True)
+ server_network = forms.GenericIPAddressField(
+ protocol="IPv4", required=True)
+ vpn_subnet = forms.GenericIPAddressField(protocol="IPv4", required=True)
is_persistent = forms.BooleanField(required=False)
- can_view_subnet = forms.BooleanField(required=False)
+ clients_can_see_each_other = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
super(VPNTenantForm, self).__init__(*args, **kwargs)
@@ -72,31 +71,30 @@
if self.instance:
self.fields['creator'].initial = self.instance.creator
+ self.fields['vpn_subnet'].initial = self.instance.vpn_subnet
self.fields[
- 'server_address'].initial = self.instance.server_address
+ 'server_network'].initial = self.instance.server_network
self.fields[
- 'client_address'].initial = self.instance.client_address
+ 'clients_can_see_each_other'].initial = self.instance.clients_can_see_each_other
self.fields['is_persistent'].initial = self.instance.is_persistent
- self.fields[
- 'can_view_subnet'].initial = self.instance.can_view_subnet
if (not self.instance) or (not self.instance.pk):
self.fields['creator'].initial = get_request().user
- self.fields['server_address'].initial = "10.8.0.1"
- self.fields['client_address'].initial = "10.8.0.2"
+ self.fields['vpn_subnet'].initial = "255.255.255.0"
+ self.fields['server_network'].initial = "10.66.77.0"
+ self.fields['clients_can_see_each_other'].initial = True
self.fields['is_persistent'].initial = True
- self.fields['can_view_subnet'].initial = False
if VPNService.get_service_objects().exists():
self.fields["provider_service"].initial = VPNService.get_service_objects().all()[
0]
def save(self, commit=True):
self.instance.creator = self.cleaned_data.get("creator")
- self.instance.server_address = self.cleaned_data.get("server_address")
- self.instance.client_address = self.cleaned_data.get("client_address")
self.instance.is_persistent = self.cleaned_data.get('is_persistent')
- self.instance.can_view_subnet = self.cleaned_data.get(
- 'can_view_subnet')
+ self.instance.vpn_subnet = self.cleaned_data.get("vpn_subnet")
+ self.instance.server_network = self.cleaned_data.get('server_network')
+ self.instance.clients_can_see_each_other = self.cleaned_data.get(
+ 'clients_can_see_each_other')
if (not self.instance.script):
self.instance.script = str(time.time()) + ".vpn"
@@ -121,19 +119,23 @@
with open("/opt/openvpn/keys/server.key") as key:
self.instance.server_key = key.readlines()
+ with open("/opt/openvpn/keys/dh2048.pem") as dh:
+ self.instance.dh = dh.readlines()
+
class Meta:
model = VPNTenant
class VPNTenantAdmin(ReadOnlyAwareAdmin):
verbose_name = "VPN Tenant Admin"
- list_display = ('id', 'backend_status_icon', 'instance')
- list_display_links = ('id', 'backend_status_icon', 'instance')
+ list_display = ('id', 'backend_status_icon', 'instance',
+ 'server_network', 'vpn_subnet')
+ list_display_links = ('id', 'backend_status_icon',
+ 'instance', 'server_network', 'vpn_subnet')
fieldsets = [(None, {'fields': ['backend_status_text', 'kind',
'provider_service', 'instance', 'creator',
- 'script_link', 'server_address',
- 'client_address', 'is_persistent',
- 'can_view_subnet'],
+ 'server_network', 'vpn_subnet', 'is_persistent',
+ 'clients_can_see_each_other', 'script_link'],
'classes': ['suit-tab suit-tab-general']})]
readonly_fields = ('backend_status_text', 'instance', 'script_link')
form = VPNTenantForm
diff --git a/xos/services/vpn/models.py b/xos/services/vpn/models.py
index 5a5919d..97c781b 100644
--- a/xos/services/vpn/models.py
+++ b/xos/services/vpn/models.py
@@ -27,14 +27,15 @@
sync_attributes = ("nat_ip", "nat_mac",)
default_attributes = {'server_key': None,
- 'server_address': '10.8.0.1',
- 'client_address': '10.8.0.2',
- 'can_view_subnet': False,
+ 'vpn_subnet': None,
+ 'server_network': None,
+ 'clients_can_see_each_other': True,
'is_persistent': True,
'script': None,
'ca_crt': None,
'server_crt': None,
- 'server_key': None}
+ 'server_key': None,
+ 'dh': None}
def __init__(self, *args, **kwargs):
vpn_services = VPNService.get_service_objects().all()
@@ -96,26 +97,26 @@
return self.addresses.get("subnet", None)
@property
- def server_address(self):
+ def server_network(self):
"""str: The IP address of the server on the VPN."""
return self.get_attribute(
- 'server_address',
- self.default_attributes['server_address'])
+ 'server_network',
+ self.default_attributes['server_network'])
- @server_address.setter
- def server_address(self, value):
- self.set_attribute("server_address", value)
+ @server_network.setter
+ def server_network(self, value):
+ self.set_attribute("server_network", value)
@property
- def client_address(self):
+ def vpn_subnet(self):
"""str: The IP address of the client on the VPN."""
return self.get_attribute(
- 'client_address',
- self.default_attributes['client_address'])
+ 'vpn_subnet',
+ self.default_attributes['vpn_subnet'])
- @client_address.setter
- def client_address(self, value):
- self.set_attribute("client_address", value)
+ @vpn_subnet.setter
+ def vpn_subnet(self, value):
+ self.set_attribute("vpn_subnet", value)
@property
def is_persistent(self):
@@ -129,15 +130,15 @@
self.set_attribute("is_persistent", value)
@property
- def can_view_subnet(self):
+ def clients_can_see_each_other(self):
"""bool: True if the client can see the subnet of the server, false otherwise."""
return self.get_attribute(
- "can_view_subnet",
- self.default_attributes['can_view_subnet'])
+ "clients_can_see_each_other",
+ self.default_attributes['clients_can_see_each_other'])
- @can_view_subnet.setter
- def can_view_subnet(self, value):
- self.set_attribute("can_view_subnet", value)
+ @clients_can_see_each_other.setter
+ def clients_can_see_each_other(self, value):
+ self.set_attribute("clients_can_see_each_other", value)
@property
def script(self):
@@ -175,6 +176,15 @@
def server_key(self, value):
self.set_attribute("server_key", value)
+ @property
+ def dh(self):
+ """str: the string for the server certificate"""
+ return self.get_attribute("dh", self.default_attributes['dh'])
+
+ @dh.setter
+ def server_key(self, value):
+ self.set_attribute("dh", value)
+
def model_policy_vpn_tenant(pk):
"""Manages the contain for the VPN Tenant."""
diff --git a/xos/synchronizers/vpn/steps/sync_vpntenant.py b/xos/synchronizers/vpn/steps/sync_vpntenant.py
index 0ac9b92..bd7a571 100644
--- a/xos/synchronizers/vpn/steps/sync_vpntenant.py
+++ b/xos/synchronizers/vpn/steps/sync_vpntenant.py
@@ -1,12 +1,16 @@
import os
import sys
-from django.db.models import Q, F
-from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
+import time
+
+from django.db.models import F, Q
from services.vpn.models import VPNTenant
+from synchronizers.base.SyncInstanceUsingAnsible import \
+ SyncInstanceUsingAnsible
parentdir = os.path.join(os.path.dirname(__file__), "..")
sys.path.insert(0, parentdir)
+
class SyncVPNTenant(SyncInstanceUsingAnsible):
"""Class for syncing a VPNTenant using Ansible."""
provides = [VPNTenant]
@@ -27,12 +31,16 @@
return objs
- def get_extra_attributes(self, o):
- return {"server_key": o.server_key.splitlines(),
- "is_persistent": o.is_persistent,
- "can_view_subnet": o.can_view_subnet,
- "server_address": o.server_address,
- "client_address": o.client_address}
+ def get_extra_attributes(self, tenant):
+ return {"server_key": tenant.server_key,
+ "is_persistent": tenant.is_persistent,
+ "vpn_subnet": tenant.vpn_subnet,
+ "server_network": tenant.server_network,
+ "clients_can_see_each_other": tenant.clients_can_see_each_other,
+ "ca_crt": tenant.ca_crt,
+ "server_crt": tenant.server_crt,
+ "dh": tenant.dh
+ }
def create_client_script(self, tenant):
script = open("/opt/xos/core/static/vpn/" + str(tenant.script), 'w')
@@ -46,6 +54,13 @@
for line in self.generate_client_conf(tenant).splitlines():
script.write(line + r"\n")
script.write("\" > client.conf\n")
+ script.write("printf \"")
+ for line in self.generate_login().splitlines():
+ script.write(line + r"\n")
+ script.write("\" > login.up\n")
+ for line in tenant.ca_crt:
+ script.write(line + r"\n")
+ script.write("\" > ca.crt\n")
# make sure openvpn is installed
script.write("apt-get update\n")
script.write("apt-get install openvpn\n")
@@ -57,6 +72,9 @@
self.create_client_script(o)
super(SyncVPNTenant, self).run_playbook(o, fields)
+ def generate_login(self):
+ return str(time.time()) + "\npassword\n"
+
def generate_client_conf(self, tenant):
"""str: Generates the client configuration to use to connect to this VPN server.
@@ -64,14 +82,19 @@
tenant (VPNTenant): The tenant to generate the client configuration for.
"""
- conf = "remote " + str(tenant.nat_ip) + "\n"
- conf += "dev tun\n"
- conf += "ifconfig " + tenant.client_address + " " + tenant.server_address + "\n"
- conf += "secret static.key"
+ conf = ("client\n" +
+ "auth-user-pass login.up\n" +
+ "dev tun\n" +
+ "proto udp\n" +
+ "remote " + str(tenant.nat_ip) + " 1194\n" +
+ "resolv-retry infinite\n" +
+ "nobind\n" +
+ "ca ca.crt\n" +
+ "comp-lzo\n" +
+ "verb 3\n")
+
if tenant.is_persistent:
- conf += "\nkeepalive 10 60\n"
- conf += "ping-timer-rem\n"
conf += "persist-tun\n"
- conf += "persist-key"
+ conf += "persist-key\n"
return conf
diff --git a/xos/synchronizers/vpn/steps/sync_vpntenant.yaml b/xos/synchronizers/vpn/steps/sync_vpntenant.yaml
index 02e2feb..2ed1154 100644
--- a/xos/synchronizers/vpn/steps/sync_vpntenant.yaml
+++ b/xos/synchronizers/vpn/steps/sync_vpntenant.yaml
@@ -5,10 +5,14 @@
user: ubuntu
sudo: yes
vars:
- server_address: {{ server_address }}
- client_address: {{ client_address }}
+ ca_crt: {{ ca_crt }}
+ server_crt: {{ server_crt }}
server_key: {{ server_key }}
+ server_network: {{ server_network }}
is_persistent: {{ is_persistent }}
+ vpn_subnet: {{ vpn_subnet }}
+ clients_can_see_each_other: {{ clients_can_see_each_other }}
+ dh: {{ dh }}
tasks:
- name: install openvpn
@@ -17,28 +21,67 @@
- name: stop openvpn
shell: killall openvpn | true
- - name: erase key
- shell: rm -f static.key
+ - name: erase server key
+ shell: rm -f server.key
- - name: write key
- shell: echo {{ '{{' }} item {{ '}}' }} >> static.key
+ - name: write server key
+ shell: echo {{ '{{' }} item {{ '}}' }} >> server.key
with_items: "{{ server_key }}"
+ - name: erase server crt
+ shell: rm -f server.crt
+
+ - name: write server crt
+ shell: echo {{ '{{' }} item {{ '}}' }} >> server.crt
+ with_items: "{{ server_crt }}"
+
+ - name: erase ca crt
+ shell: rm -f ca.crt
+
+ - name: write ca crt
+ shell: echo {{ '{{' }} item {{ '}}' }} >> ca.crt
+ with_items: "{{ ca_crt }}"
+
+ - name: erase dh
+ shell: rm -f dh2048.pem
+
+ - name: write dh
+ shell: echo {{ '{{' }} item {{ '}}' }} >> dh2048.pem
+ with_items: "{{ dh }}"
+
- name: erase config
shell: rm -f server.conf
+ - name: erase auth script
+ shell: rm -f auth.sh
+
+ - name: write auth script
+ shell: "exit 0" > auth.sh
+
- name: write base config
shell:
|
- printf "dev tun
- ifconfig {{ server_address }} {{ client_address }}
- secret static.key" > server.conf
+ printf "script-security 3 system
+ port 1194
+ proto udp
+ dev tun
+ cert server.crt
+ key server.key
+ dh dh2048.pem
+ server {{ server_network }} {{ vpn_subnet }}
+ ifconfig-pool-persist ipp.txt
+ comp-lzo
+ status openvpn-status.log
+ verb 3
+ auth-user-pass-verify auth.sh via-file
+ client-cert-not-required
+ username-as-common-name
+ " > server.conf
- name: write persistent config
shell:
|
printf "\nkeepalive 10 60
- ping-timer-rem
persist-tun
persist-key" >> server.conf
when: {{ is_persistent }}