wireguardCreate.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import smtplib
  5. import subprocess
  6. from email.mime.multipart import MIMEMultipart
  7. from email.mime.text import MIMEText
  8. def check_env (member_id):
  9. """
  10. Checks if wireguard is correctly installed, the script is run as
  11. root and the member id is correct.
  12. """
  13. wgInstalled = os.system("wg")
  14. if os.geteuid() != 0:
  15. print("On a besoin des droits root pour créer un accès VPN.")
  16. print("Relancez la commande préfixée d'un sudo.")
  17. raise Exception("Got root?")
  18. if wgInstalled != 0:
  19. print("Wireguard ne semble pas être installé sur votre système.")
  20. print("Il faudrait installer wireguard-tools et wireguard-dkms avant\
  21. d'utiliser ce script")
  22. raise Exception("Install wg")
  23. if member_id == 0 and member_id < 255:
  24. print("On est parti du principe que les IDs des membres commencent à 1.")
  25. print("Ah, aussi, pour le moment, on est aussi partis du principe que ça \
  26. s'arrête à 254.")
  27. print("Si on a plus de 254 membres, premièrement, FÉLICITATIONS venant\
  28. du Félix du passé. Par contre, il faut repenser l'adressage des \
  29. IPs du VPN maintenant :( Ranson du succès j'immagine.")
  30. raise Exception("Wrong member_id")
  31. def gen_wg_keys ():
  32. """
  33. Generates both the private and the public wireguard key of the new member.
  34. """
  35. priv = subprocess.run(["wg","genkey"], stdout=subprocess.STDOUT).decode(encoding='UTF-8').rstrip()
  36. psk = subprocess.run(["wg","genpsk"], stdout=subprocess.STDOUT).decode(encoding='UTF-8').rstrip()
  37. pub = subprocess.run(["bash", "-c", "echo EMrXWE+Qw4i0+sAgoNHVECgR+e1nWmEF3qYU4ftWUG8= | wg pubkey"]\
  38. , stdout=subprocess.PIPE).decode(encoding='UTF-8').rstrip()
  39. # TODO: better error check.
  40. if os.system(gen_key_cmd) != 0:
  41. print("Erreur lors de la génération des clés wireguard.")
  42. print("Contactez un administrateur technique en lui envoyant le message d'erreur ci-dessus.")
  43. sys.exit(1)
  44. return (priv, psk, pub)
  45. def update_wg_config (member_id, config_file, pubkey, pshkey):
  46. """
  47. Generate the wireguard configuration for this new member.
  48. """
  49. wg_new_peer = '''
  50. [Peer]
  51. PublicKey = {0}
  52. PresharedKey = {1}
  53. AllowedIPs = 10.0.0.{2}/24, fd00::{2}/64
  54. '''.format(pubkey, pshkey, member_id)
  55. with open(config_file, "a") as wg_file:
  56. wg_file.write(wg_config)
  57. class Email:
  58. """
  59. Not really necessary, but I keep on forgetting most of an email arguments
  60. and I'm tired of debugging this class of error... Too bad we don't have any
  61. record type in this language.
  62. PS: I hate python.
  63. """
  64. def __init__(self, username, passwd, from_addr, to_addr, server):
  65. self.username = username
  66. self.passwd = passwd
  67. self.from_addr = from_addr
  68. self.to_addr = to_addr
  69. self.server = server
  70. def send_mail(email, wgconfig):
  71. """
  72. Send the private key by email.
  73. email:
  74. - username
  75. - passwd
  76. - from_addr
  77. - to_addr
  78. - server
  79. """
  80. from_addr = 'bureau@baionet.fr'
  81. password = email.passwd
  82. msg = MIMEMultipart()
  83. msg['Subject'] = "Votre acces VPN Baionet"
  84. msg['From'] = email.from_addr
  85. msg['To'] = [email.to_addr]
  86. body = '''
  87. blahblah, cf le wiki blahblahblah
  88. '''
  89. mail_static_text = random.choice(messages)
  90. msg.attach([MIMEText(body), MIMEText(config)])
  91. username = email.username
  92. server = smtplib.SMTP(email.server)
  93. server.ehlo()
  94. server.starttls()
  95. server.login(email.username, email.passwd)
  96. server.sendmail(email.from_addr, email.to_addr, msg.as_string())
  97. server.quit()
  98. # Main Function
  99. # =============
  100. # *************
  101. # =============
  102. # 1- Parse email/member id.
  103. # 2- Génère les clés wireguard.
  104. # 3- Crée/déploie la configuration wireguard.
  105. # 4- Crée/déploie la nouvelle interface réseau.
  106. # 5- Envoie la clé à l'utilisateur (email/manuellement)
  107. if __name__ == '__main__':
  108. key_dir = "/etc/wireguard/keys"
  109. wg_config_dir = "/etc/wireguard"
  110. if_config_dir = "/etc/interfaces"
  111. # On récupère le numéro d'adhérant et l'email d'un nouveau membre.
  112. member_email = input("EMail du nouveau membre: ")
  113. try:
  114. member_id = int(input("Numéro d'adhérant du nouveau membre: "))
  115. except Exception as e:
  116. print("ERREUR: Le numéro d'adhérant est en théorie un entier entre 1 et 254.")
  117. try:
  118. check_env(member_id)
  119. except Exception as e:
  120. print("ERREUR: problème d'environnement: {}".format(e))
  121. sys.exit(1)
  122. print("[+] Génération des clés wireguard")
  123. (privkey_path,pubkey_path) = gen_wg_keys(member_id, tmp_key_dir)
  124. print("[+] Création de la configuration wireguard")
  125. create_wg_config(member_id, wg_config_dir, privkey_path, pubkey_path)
  126. print("[+] Création de la nouvelle interface réseau")
  127. create_if_file(member_id, if_config_dir)
  128. print("[+] Chargement de la nouvelle interface réseau")
  129. os.system("systemctl restart networking")
  130. print("[+] Envoi de la clé privée au nouveau membre")
  131. try:
  132. username = os.environ['SMTP_USERNAME']
  133. passwd = os.environ['SMTP_PASSWD']
  134. server = os.environ['SMTP_SERVER']
  135. email = Email(username, passwd, "bureau@baionet.fr", member_email, "smtp://server")
  136. send_email(email, privkey_path, "")
  137. except Exception as e:
  138. print("ERREUR: erreur lors de l'envoi de l'email: {}".format(e))
  139. print("Veuillez envoyer tout ce message d'erreur à la liste bayonetek@framalistes.org")
  140. sys.exit(1)
  141. print("[+] Nettoyage")
  142. print("[+] DONE")