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 sqlite3
|
||||||
import sys
|
import os
|
||||||
from flask import Flask, request, jsonify
|
from flask import Flask, request, jsonify, render_template, Response
|
||||||
app = Flask(__name__)
|
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'
|
DATABASE='/data/database.sqlite3'
|
||||||
db = sqlite3.connect(DATABASE)
|
db = sqlite3.connect(DATABASE)
|
||||||
cu = db.cursor()
|
cu = db.cursor()
|
||||||
|
@ -10,11 +19,15 @@ db.execute('SELECT name FROM sqlite_master')
|
||||||
if len(cu.fetchall()) == 0:
|
if len(cu.fetchall()) == 0:
|
||||||
print('creating database schema...')
|
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 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()
|
db.commit()
|
||||||
cu.close()
|
cu.close()
|
||||||
db.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('/')
|
@app.route('/')
|
||||||
def hello_world():
|
def hello_world():
|
||||||
return 'It works!'
|
return 'It works!'
|
||||||
|
@ -45,24 +58,113 @@ def post_users():
|
||||||
return jsonify({'status': 'ok'})
|
return jsonify({'status': 'ok'})
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
return jsonify({'status': 'error', 'message': str(e)}), 409
|
return jsonify({'status': 'error', 'message': str(e)}), 409
|
||||||
finally:
|
finally:
|
||||||
db.commit()
|
db.commit()
|
||||||
cu.close()
|
cu.close()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
@app.route('/gateways', methods=['GET'])
|
@app.route('/gateways', methods=['GET'])
|
||||||
def get_gateway():
|
def get_gateways():
|
||||||
db = sqlite3.connect(DATABASE)
|
db = sqlite3.connect(DATABASE)
|
||||||
cu = db.cursor()
|
cu = db.cursor()
|
||||||
|
|
||||||
gateways = []
|
gateways = []
|
||||||
for row in cu.execute('SELECT id, name, user FROM gateway'):
|
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], 'name': row[1], 'user': row[2], 'network': row[3]})
|
gateways.append({'id': row[0], 'subid': row[1], 'name': row[2], 'user': row[3]})
|
||||||
|
|
||||||
cu.close()
|
cu.close()
|
||||||
db.close()
|
db.close()
|
||||||
return jsonify(gateways)
|
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__':
|
if __name__ == '__main__':
|
||||||
app.run(host="::", port=5000, debug=True)
|
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