wireguardCreate.py 6.4 KB

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