second commit
This commit is contained in:
parent
267bd9d888
commit
43790ef31c
|
@ -0,0 +1,3 @@
|
|||
[submodule "easy-rsa"]
|
||||
path = easy-rsa
|
||||
url = https://github.com/OpenVPN/easy-rsa.git
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a9cecc747c419197d9540ccd46259559e271788a
|
116
main.py
116
main.py
|
@ -1,8 +1,17 @@
|
|||
import sqlite3
|
||||
import sys
|
||||
from flask import Flask, request, jsonify
|
||||
import os
|
||||
from flask import Flask, request, jsonify, render_template, Response
|
||||
app = Flask(__name__)
|
||||
|
||||
class Ex(Exception):
|
||||
def __init__(self, code, message):
|
||||
self._code = code
|
||||
self._message = message
|
||||
def getCode(self):
|
||||
return self._code
|
||||
def __str__(self):
|
||||
return self._message
|
||||
|
||||
DATABASE='/data/database.sqlite3'
|
||||
db = sqlite3.connect(DATABASE)
|
||||
cu = db.cursor()
|
||||
|
@ -10,11 +19,15 @@ db.execute('SELECT name FROM sqlite_master')
|
|||
if len(cu.fetchall()) == 0:
|
||||
print('creating database schema...')
|
||||
db.execute('CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT UNIQUE)')
|
||||
db.execute('CREATE TABLE IF NOT EXISTS gateway (id INTEGER PRIMARY KEY, name TEXT UNIQUE, user INTEGER REFERENCES user(id))')
|
||||
db.execute('CREATE TABLE IF NOT EXISTS gateway (id INTEGER PRIMARY KEY, subid INTEGER NOT NULL, name TEXT UNIQUE, user INTEGER NOT NULL REFERENCES user(id))')
|
||||
db.commit()
|
||||
cu.close()
|
||||
db.close()
|
||||
|
||||
os.environ['EASYRSA_PKI'] = '/data/pki'
|
||||
os.environ['EASYRSA_BATCH'] = '1'
|
||||
os.environ['PATH'] = os.environ['PATH'] + ':' + os.getcwd() + '/easy-rsa/easyrsa3'
|
||||
|
||||
@app.route('/')
|
||||
def hello_world():
|
||||
return 'It works!'
|
||||
|
@ -45,24 +58,113 @@ def post_users():
|
|||
return jsonify({'status': 'ok'})
|
||||
except sqlite3.Error as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 409
|
||||
finally:
|
||||
finally:
|
||||
db.commit()
|
||||
cu.close()
|
||||
db.close()
|
||||
|
||||
@app.route('/gateways', methods=['GET'])
|
||||
def get_gateway():
|
||||
def get_gateways():
|
||||
db = sqlite3.connect(DATABASE)
|
||||
cu = db.cursor()
|
||||
|
||||
gateways = []
|
||||
for row in cu.execute('SELECT id, name, user FROM gateway'):
|
||||
gateways.append({'id': row[0], 'name': row[1], 'user': row[2], 'network': row[3]})
|
||||
for row in cu.execute('SELECT g.id, g.subid, g.name, u.name FROM gateway AS g INNER JOIN user AS u ON u.id = g.user'):
|
||||
gateways.append({'id': row[0], 'subid': row[1], 'name': row[2], 'user': row[3]})
|
||||
|
||||
cu.close()
|
||||
db.close()
|
||||
return jsonify(gateways)
|
||||
|
||||
@app.route('/gateways', methods=['POST'])
|
||||
def post_gateways():
|
||||
db = sqlite3.connect(DATABASE)
|
||||
cu = db.cursor()
|
||||
|
||||
try:
|
||||
name = request.json['name']
|
||||
user = request.json['user']
|
||||
|
||||
# TODO sanitize name, it must be a FQDN
|
||||
|
||||
used_gateway_subids = []
|
||||
for row in cu.execute('SELECT g.subid, u.id FROM gateway AS g INNER JOIN user AS u ON g.user = u.id WHERE u.name = ?', [str(user,)]):
|
||||
used_gateway_subids.append(row[0])
|
||||
userid = row[1]
|
||||
|
||||
# search for an empty id for gateway
|
||||
for subid in range(0, 15):
|
||||
if subid not in used_gateway_subids:
|
||||
break
|
||||
|
||||
if subid in used_gateway_subids:
|
||||
raise Ex(403, 'exit: maximum number of gateways reached for user')
|
||||
|
||||
cu.execute('INSERT INTO gateway (subid, name, user) VALUES (?, ?, (SELECT id FROM user WHERE name = ?))', [subid, str(name,), str(user,)])
|
||||
|
||||
os.environ['EASYRSA_REQ_CN'] = name
|
||||
|
||||
r = os.system('easyrsa gen-req {} nopass'.format(name))
|
||||
if r != 0:
|
||||
raise Ex(500, 'exit: {} cannot gen-req'.format(r))
|
||||
r = os.system('easyrsa sign-req client {}'.format(name))
|
||||
if r != 0:
|
||||
raise Ex(500, 'exit: {} cannot sign-req'.format(r))
|
||||
|
||||
ipid = '{:x}{:x}'.format(userid, subid)
|
||||
|
||||
address = '2001:470:c844::' + ipid + '0/64'
|
||||
network = '2001:470:c844:' + ipid + '0::/60'
|
||||
|
||||
staticclient = render_template('staticclient', address=address, network=network)
|
||||
with open('/data/ovpn/clients/' + name, 'w') as f:
|
||||
f.write(staticclient)
|
||||
|
||||
db.commit()
|
||||
return jsonify({'status': 'ok'})
|
||||
except KeyError as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 400
|
||||
except sqlite3.Error as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 409
|
||||
except Ex as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), e.getCode()
|
||||
finally:
|
||||
cu.close()
|
||||
db.close()
|
||||
|
||||
@app.route('/gateway/<fqdn>', methods=['GET'])
|
||||
def get_gateway(fqdn):
|
||||
db = sqlite3.connect(DATABASE)
|
||||
cu = db.cursor()
|
||||
|
||||
gateway = dict()
|
||||
for row in cu.execute('SELECT g.id, g.subid, g.name, u.name FROM gateway AS g INNER JOIN user AS u ON u.id = g.user'):
|
||||
gateway['id'] = row[0]
|
||||
gateway['subid'] = row[1]
|
||||
gateway['name'] = row[2]
|
||||
gateway['user'] = row[3]
|
||||
|
||||
cu.close()
|
||||
db.close()
|
||||
|
||||
return jsonify(gateway)
|
||||
|
||||
@app.route('/gateway/<fqdn>/config', methods=['GET'])
|
||||
def get_gateway_config(fqdn):
|
||||
# TODO sanity check FQDN
|
||||
# WARNING: maybe you want to do more than a simple sanity check,
|
||||
# or you have to trust the user of these API
|
||||
# eg: he could retrieve the CA.key !!!
|
||||
|
||||
with open(os.environ['EASYRSA_PKI'] + '/issued/' + fqdn + '.crt') as f:
|
||||
cert = f.read()
|
||||
with open(os.environ['EASYRSA_PKI'] + '/private/' + fqdn + '.key') as f:
|
||||
key = f.read()
|
||||
with open(os.environ['EASYRSA_PKI'] + '/ca.crt') as f:
|
||||
ca = f.read()
|
||||
|
||||
return Response(render_template('config.ovpn', ca=ca, cert=cert, key=key), mimetype='text/plain')
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host="::", port=5000, debug=True)
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
#############################################
|
||||
# OpenVPN 2.0 client config file #
|
||||
#############################################
|
||||
# #
|
||||
# golem.linux.it #
|
||||
# #
|
||||
# in caso di problemi visitare la pagina #
|
||||
# https://golem.linux.it/wiki/VPN_del_GOLEM #
|
||||
# https://golem.linux.it/wiki/IPv6_@_GOLEM #
|
||||
# #
|
||||
# se non si riesce a risolvere, contattare #
|
||||
# l'amministratore di rete #
|
||||
#############################################
|
||||
|
||||
# Specify that we are a client and that we
|
||||
# will be pulling certain config file directives
|
||||
# from the server.
|
||||
client
|
||||
|
||||
# Use the same setting as you are using on
|
||||
# the server.
|
||||
# On most systems, the VPN will not function
|
||||
# unless you partially or fully disable
|
||||
# the firewall for the TUN/TAP interface.
|
||||
dev tun
|
||||
|
||||
# Windows needs the TAP-Win32 adapter name
|
||||
# from the Network Connections panel
|
||||
# if you have more than one. On XP SP2,
|
||||
# you may need to disable the firewall
|
||||
# for the TAP adapter.
|
||||
;dev-node MyTap
|
||||
|
||||
# Are we connecting to a TCP or
|
||||
# UDP server? Use the same setting as
|
||||
# on the server.
|
||||
proto udp6
|
||||
|
||||
# The hostname/IP and port of the server.
|
||||
# You can have multiple remote entries
|
||||
# to load balance between the servers.
|
||||
remote vpntest.andromeda.golem.linux.it 6666
|
||||
|
||||
# Choose a random host from the remote
|
||||
# list for load-balancing. Otherwise
|
||||
# try hosts in the order specified.
|
||||
;remote-random
|
||||
|
||||
# Keep trying indefinitely to resolve the
|
||||
# host name of the OpenVPN server. Very useful
|
||||
# on machines which are not permanently connected
|
||||
# to the internet such as laptops.
|
||||
resolv-retry infinite
|
||||
|
||||
# Most clients don't need to bind to
|
||||
# a specific local port number.
|
||||
nobind
|
||||
|
||||
# Downgrade privileges after initialization (non-Windows only)
|
||||
user nobody
|
||||
group nobody
|
||||
|
||||
# Try to preserve some state across restarts.
|
||||
persist-key
|
||||
persist-tun
|
||||
|
||||
# If you are connecting through an
|
||||
# HTTP proxy to reach the actual OpenVPN
|
||||
# server, put the proxy server/IP and
|
||||
# port number here. See the man page
|
||||
# if your proxy server requires
|
||||
# authentication.
|
||||
;http-proxy-retry # retry on connection failures
|
||||
;http-proxy [proxy server] [proxy port #]
|
||||
|
||||
# Wireless networks often produce a lot
|
||||
# of duplicate packets. Set this flag
|
||||
# to silence duplicate packet warnings.
|
||||
;mute-replay-warnings
|
||||
|
||||
# SSL/TLS parms.
|
||||
# See the server config file for more
|
||||
# description. It's best to use
|
||||
# a separate .crt/.key file pair
|
||||
# for each client. A single ca
|
||||
# file can be used for all clients.
|
||||
#ca /home/golem/ca.crt
|
||||
#cert /home/golemiss3.golem.it.crt
|
||||
#key /home/golem/iss3.golem.it.key
|
||||
|
||||
# Verify server certificate by checking that the
|
||||
# certicate has the correct key usage set.
|
||||
# This is an important precaution to protect against
|
||||
# a potential attack discussed here:
|
||||
# http://openvpn.net/howto.html#mitm
|
||||
#
|
||||
# To use this feature, you will need to generate
|
||||
# your server certificates with the keyUsage set to
|
||||
# digitalSignature, keyEncipherment
|
||||
# and the extendedKeyUsage to
|
||||
# serverAuth
|
||||
# EasyRSA can do this for you.
|
||||
remote-cert-tls server
|
||||
|
||||
# If a tls-auth key is used on the server
|
||||
# then every client must also have the key.
|
||||
; tls-auth ta.key 1
|
||||
|
||||
# Select a cryptographic cipher.
|
||||
# If the cipher option is used on the server
|
||||
# then you must also specify it here.
|
||||
# Note that 2.4 client/server will automatically
|
||||
# negotiate AES-256-GCM in TLS mode.
|
||||
# See also the ncp-cipher option in the manpage
|
||||
cipher AES-256-CBC
|
||||
|
||||
# Enable compression on the VPN link.
|
||||
# Don't enable this unless it is also
|
||||
# enabled in the server config file.
|
||||
; comp-lzo
|
||||
|
||||
# Set log file verbosity.
|
||||
verb 3
|
||||
|
||||
# Silence repeating messages
|
||||
;mute 20
|
||||
|
||||
# Periodically ping the server,
|
||||
# and if it doesn't answer after a timeout
|
||||
# try to reconnect again
|
||||
keepalive 30 120
|
||||
|
||||
<ca>
|
||||
{{ ca }}
|
||||
</ca>
|
||||
<cert>
|
||||
{{ cert }}
|
||||
</cert>
|
||||
<key>
|
||||
{{ key }}
|
||||
</key>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ifconfig-ipv6-push {{ address }}
|
||||
iroute-ipv6 {{ network }}
|
||||
|
Loading…
Reference in New Issue