123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- #!/usr/bin/env python3
- import os
- import sys
- import smtplib
- from email.mime.multipart import MIMEMultipart
- from email.mime.text import MIMEText
- def check_env (member_id):
- """
- Checks if wireguard is correctly installed, the script is run as
- root and the member id is correct.
- """
- wgInstalled = os.system("wg")
- if os.geteuid() != 0:
- print("On a besoin des droits root pour créer un accès VPN.")
- print("Relancez la commande préfixée d'un sudo.")
- raise Exception("Got root?")
- if wgInstalled != 0:
- print("Wireguard ne semble pas être installé sur votre système.")
- print("Il faudrait installer wireguard-tools et wireguard-dkms avant\
- d'utiliser ce script")
- raise Exception("Install wg")
- if member_id == 0 and member_id < 255:
- print("On est parti du principe que les IDs des membres commencent à 1.")
- print("Ah, aussi, pour le moment, on est aussi partis du principe que ça \
- s'arrête à 254.")
- print("Si on a plus de 254 membres, premièrement, FÉLICITATIONS venant\
- du Félix du passé. Par contre, il faut repenser l'adressage des \
- IPs du VPN maintenant :( Ranson du succès j'immagine.")
- raise Exception("Wrong member_id")
- def gen_wg_keys (member_id, key_dir):
- """
- Generates both the private and the public wireguard key of the new member.
- """
- privkey_path = os.path.join(key_dir,"{0}.key".format(member_id))
- pubkey_path = os.path.join(key_dir,"{0}.public".format(member_id))
- gen_key_cmd = "wg genkey | tee {0} | wg pubkey > {1}".format(privkey_path, pubkey_path)
- if os.system(gen_key_cmd) != 0:
- print("Erreur lors de la génération des clés wireguard.")
- print("Contactez un administrateur technique en lui envoyant le message d'erreur ci-dessus.")
- sys.exit(1)
- return (privkey_path, pubkey_path)
- def create_wg_config (member_id, config_dir, wg_server_privkey, pubkey_path):
- """
- Generate the wireguard configuration for this new member.
- """
- wg_filename = os.path.join (config_dir, "wg{0}.conf".format(member_id))
- with open(pubkey_path, "r") as pub_file:
- wg_peer_pubkey = pub_file.read()
- wg_config = '''
- [Interface]
- PrivateKey = {0}
- ListenPort = 51820
- [Peer]
- PublicKey = {1}
- AllowedIPs = 0.0.0.0/24
- '''.format(wg_server_privkey, wg_peer_pubkey)
- with open(wgFileName, "w") as wg_file:
- wg_file.write(wg_config)
- def create_if_file (member_id, config_dir):
- """
- Create and configure the new network interface for this new member.
- """
- iface_name = "wg{0}".format(member_id)
- iface_addrv4 = "10.0.0.{0}".format(member_id)
- iface_filename = os.path.join (config_dir, "{}.conf".format(iface_name))
- iface_config = '''
- auto {0}
- iface {0} inet static
- address {1}
- netmask 255.255.255.0
- pre-up ip link add $IFACE type wireguard
- pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf
- post-down ip link del $IFACE
- '''.format(iface_name, iface_addrv4)
- with open(iface_filename, "w") as iface_file:
- iface_file.write(iface_config)
- class Email:
- """
- Not really necessary, but I keep on forgetting most of an email arguments
- and I'm tired of debugging this class of error... Too bad we don't have any
- record type in this language.
- PS: I hate python.
- """
- def __init__(self, username, passwd, from_addr, to_addr, server):
- self.username = username
- self.passwd = passwd
- self.from_addr = from_addr
- self.to_addr = to_addr
- self.server = server
- def send_mail(email, wgconfig):
- """
- Send the private key by email.
- email:
- - username
- - passwd
- - from_addr
- - to_addr
- - server
- """
- from_addr = 'bureau@baionet.fr'
- password = email.passwd
- msg = MIMEMultipart()
- msg['Subject'] = "Votre acces VPN Baionet"
- msg['From'] = email.from_addr
- msg['To'] = [email.to_addr]
- body = '''
- blahblah, cf le wiki blahblahblah
- '''
- mail_static_text = random.choice(messages)
- msg.attach([MIMEText(body), MIMEText(config)])
- username = email.username
- server = smtplib.SMTP(email.server)
- server.ehlo()
- server.starttls()
- server.login(email.username, email.passwd)
- server.sendmail(email.from_addr, email.to_addr, msg.as_string())
- server.quit()
- # Main Function
- # =============
- # *************
- # =============
- # 1- Parse email/member id.
- # 2- Génère les clés wireguard.
- # 3- Crée/déploie la configuration wireguard.
- # 4- Crée/déploie la nouvelle interface réseau.
- # 5- Envoie la clé à l'utilisateur (email/manuellement)
- if __name__ == '__main__':
- key_dir = "/etc/wireguard/keys"
- wg_config_dir = "/etc/wireguard"
- if_config_dir = "/etc/interfaces"
- # On récupère le numéro d'adhérant et l'email d'un nouveau membre.
- member_email = input("EMail du nouveau membre: ")
- try:
- member_id = int(input("Numéro d'adhérant du nouveau membre: "))
- except Exception as e:
- print("ERREUR: Le numéro d'adhérant est en théorie un entier entre 1 et 254.")
- try:
- check_env(member_id)
- except Exception as e:
- print("ERREUR: problème d'environnement: {}".format(e))
- sys.exit(1)
- print("[+] Génération des clés wireguard")
- (privkey_path,pubkey_path) = gen_wg_keys(member_id, tmp_key_dir)
- print("[+] Création de la configuration wireguard")
- create_wg_config(member_id, wg_config_dir, privkey_path, pubkey_path)
- print("[+] Création de la nouvelle interface réseau")
- create_if_file(member_id, if_config_dir)
- print("[+] Chargement de la nouvelle interface réseau")
- os.system("systemctl restart networking")
- print("[+] Envoi de la clé privée au nouveau membre")
- try:
- username = os.environ['SMTP_USERNAME']
- passwd = os.environ['SMTP_PASSWD']
- server = os.environ['SMTP_SERVER']
- email = Email(username, passwd, "bureau@baionet.fr", member_email, "smtp://server")
- send_email(email, privkey_path, "")
- except Exception as e:
- print("ERREUR: erreur lors de l'envoi de l'email: {}".format(e))
- print("Veuillez envoyer tout ce message d'erreur à la liste bayonetek@framalistes.org")
- sys.exit(1)
- print("[+] Nettoyage")
- print("[+] DONE")
|