mirror of
https://github.com/k4yt3x/wg-meshconf.git
synced 2025-08-16 08:38:05 +02:00
1.1.5 patch for avalon_framework 1.6.0
This commit is contained in:
@ -10,7 +10,7 @@ Licensed under the GNU General Public License Version 3 (GNU GPL v3),
|
|||||||
available at: https://www.gnu.org/licenses/gpl-3.0.txt
|
available at: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
(C) 2018 K4YT3X
|
(C) 2018 K4YT3X
|
||||||
"""
|
"""
|
||||||
import avalon_framework as avalon
|
from avalon_framework import Avalon
|
||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
import re
|
import re
|
||||||
@ -19,7 +19,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
VERSION = '1.1.4'
|
VERSION = '1.1.5'
|
||||||
COMMANDS = [
|
COMMANDS = [
|
||||||
'Interactive',
|
'Interactive',
|
||||||
'ShowPeers',
|
'ShowPeers',
|
||||||
@ -139,7 +139,7 @@ class ProfileManager(object):
|
|||||||
Open the pickle file, deserialize the content and
|
Open the pickle file, deserialize the content and
|
||||||
load it back into the profile manager.
|
load it back into the profile manager.
|
||||||
"""
|
"""
|
||||||
avalon.dbgInfo('Loading profile from: {}'.format(profile_path))
|
Avalon.dbgInfo('Loading profile from: {}'.format(profile_path))
|
||||||
with open(profile_path, 'rb') as profile:
|
with open(profile_path, 'rb') as profile:
|
||||||
pm.peers = pickle.load(profile)
|
pm.peers = pickle.load(profile)
|
||||||
profile.close()
|
profile.close()
|
||||||
@ -154,18 +154,18 @@ class ProfileManager(object):
|
|||||||
# If profile already exists (file or link), ask the user if
|
# If profile already exists (file or link), ask the user if
|
||||||
# we should overwrite it.
|
# we should overwrite it.
|
||||||
if os.path.isfile(profile_path) or os.path.islink(profile_path):
|
if os.path.isfile(profile_path) or os.path.islink(profile_path):
|
||||||
if not avalon.ask('File already exists. Overwrite?', True):
|
if not Avalon.ask('File already exists. Overwrite?', True):
|
||||||
avalon.warning('Aborted saving profile')
|
Avalon.warning('Aborted saving profile')
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Abort if profile_path points to a directory
|
# Abort if profile_path points to a directory
|
||||||
if os.path.isdir(profile_path):
|
if os.path.isdir(profile_path):
|
||||||
avalon.warning('Destination path is a directory')
|
Avalon.warning('Destination path is a directory')
|
||||||
avalon.warning('Aborted saving profile')
|
Avalon.warning('Aborted saving profile')
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Finally, write the profile into the destination file
|
# Finally, write the profile into the destination file
|
||||||
avalon.dbgInfo('Writing profile to: {}'.format(profile_path))
|
Avalon.dbgInfo('Writing profile to: {}'.format(profile_path))
|
||||||
with open(profile_path, 'wb') as profile:
|
with open(profile_path, 'wb') as profile:
|
||||||
pickle.dump(pm.peers, profile)
|
pickle.dump(pm.peers, profile)
|
||||||
profile.close()
|
profile.close()
|
||||||
@ -175,9 +175,9 @@ class ProfileManager(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Warn the user before flushing configurations
|
# Warn the user before flushing configurations
|
||||||
avalon.warning('This will flush the currently loaded profile!')
|
Avalon.warning('This will flush the currently loaded profile!')
|
||||||
if len(self.peers) != 0:
|
if len(self.peers) != 0:
|
||||||
if not avalon.ask('Continue?', False):
|
if not Avalon.ask('Continue?', False):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Reset self.peers and start enrolling new peer data
|
# Reset self.peers and start enrolling new peer data
|
||||||
@ -203,7 +203,7 @@ def print_peer_config(peer):
|
|||||||
|
|
||||||
Input takes one Peer object.
|
Input takes one Peer object.
|
||||||
"""
|
"""
|
||||||
avalon.info('Peer {} information summary:'.format(peer.address))
|
Avalon.info('Peer {} information summary:'.format(peer.address))
|
||||||
if peer.address:
|
if peer.address:
|
||||||
print('Address: {}'.format(peer.address))
|
print('Address: {}'.format(peer.address))
|
||||||
if peer.public_address:
|
if peer.public_address:
|
||||||
@ -225,40 +225,40 @@ def enroll_peer():
|
|||||||
|
|
||||||
# Get peer tunnel address
|
# Get peer tunnel address
|
||||||
while True:
|
while True:
|
||||||
address = avalon.gets('Address (leave empty if client only): ')
|
address = Avalon.gets('Address (leave empty if client only): ')
|
||||||
result = re.match('^(?:\d{1,3}\.){3}\d{1,3}/{1}(?:\d\d?)?$', address)
|
result = re.match('^(?:\d{1,3}\.){3}\d{1,3}/{1}(?:\d\d?)?$', address)
|
||||||
if result is None:
|
if result is None:
|
||||||
avalon.error('Invalid address entered')
|
Avalon.error('Invalid address entered')
|
||||||
avalon.error('Please use CIDR notation (e.g. 10.0.0.0/8)')
|
Avalon.error('Please use CIDR notation (e.g. 10.0.0.0/8)')
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
# Get peer public IP address
|
# Get peer public IP address
|
||||||
while True:
|
while True:
|
||||||
public_address = avalon.gets('Public address (leave empty if client only): ')
|
public_address = Avalon.gets('Public address (leave empty if client only): ')
|
||||||
result = re.match('^(?:\d{1,3}\.){3}\d{1,3}(?:/\d\d?)?$', public_address)
|
result = re.match('^(?:\d{1,3}\.){3}\d{1,3}(?:/\d\d?)?$', public_address)
|
||||||
if result is None and public_address != '': # field not required
|
if result is None and public_address != '': # field not required
|
||||||
avalon.error('Invalid IP address entered')
|
Avalon.error('Invalid IP address entered')
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
|
||||||
# Get peer listening port
|
# Get peer listening port
|
||||||
listen_port = avalon.gets('Listen port (leave empty for client): ')
|
listen_port = Avalon.gets('Listen port (leave empty for client): ')
|
||||||
|
|
||||||
# Get peer private key
|
# Get peer private key
|
||||||
private_key = avalon.gets('Private key (leave empty for auto generation): ')
|
private_key = Avalon.gets('Private key (leave empty for auto generation): ')
|
||||||
if private_key == '':
|
if private_key == '':
|
||||||
private_key = wg.genkey()
|
private_key = wg.genkey()
|
||||||
|
|
||||||
# Ask if this peer needs to be actively connected
|
# Ask if this peer needs to be actively connected
|
||||||
# if peer is behind NAT and needs to be accessed actively
|
# if peer is behind NAT and needs to be accessed actively
|
||||||
# PersistentKeepalive must be turned on (!= 0)
|
# PersistentKeepalive must be turned on (!= 0)
|
||||||
keep_alive = avalon.ask('Keep alive?', False)
|
keep_alive = Avalon.ask('Keep alive?', False)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
preshared_key = False
|
preshared_key = False
|
||||||
if avalon.ask('Use a preshared key?', True):
|
if Avalon.ask('Use a preshared key?', True):
|
||||||
preshared_key = avalon.gets('Preshared Key (leave empty for auto generation): ')
|
preshared_key = Avalon.gets('Preshared Key (leave empty for auto generation): ')
|
||||||
if preshared_key == '':
|
if preshared_key == '':
|
||||||
preshared_key = wg.genpsk()
|
preshared_key = wg.genpsk()
|
||||||
peer = Peer(address, private_key, keep_alive, listen_port, preshared_key)
|
peer = Peer(address, private_key, keep_alive, listen_port, preshared_key)
|
||||||
@ -276,30 +276,30 @@ def generate_configs(output_path):
|
|||||||
the CONFIG_OUTPUT directory.
|
the CONFIG_OUTPUT directory.
|
||||||
"""
|
"""
|
||||||
if len(pm.peers) == 0:
|
if len(pm.peers) == 0:
|
||||||
avalon.warning('No peers configured, exiting')
|
Avalon.warning('No peers configured, exiting')
|
||||||
exit(0)
|
exit(0)
|
||||||
if len(pm.peers) == 1:
|
if len(pm.peers) == 1:
|
||||||
avalon.warning('Only one peer configured')
|
Avalon.warning('Only one peer configured')
|
||||||
|
|
||||||
avalon.info('Generating configuration files')
|
Avalon.info('Generating configuration files')
|
||||||
|
|
||||||
# Abort is destination is a file / link
|
# Abort is destination is a file / link
|
||||||
if os.path.isfile(output_path) or os.path.islink(output_path):
|
if os.path.isfile(output_path) or os.path.islink(output_path):
|
||||||
avalon.warning('Destination path is a file / link')
|
Avalon.warning('Destination path is a file / link')
|
||||||
avalon.warning('Aborting configuration generation')
|
Avalon.warning('Aborting configuration generation')
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Ask if user wants to create the output directory if it doesn't exist
|
# Ask if user wants to create the output directory if it doesn't exist
|
||||||
if not os.path.isdir(output_path):
|
if not os.path.isdir(output_path):
|
||||||
if avalon.ask('Output directory doesn\'t exist. Create output directory?', True):
|
if Avalon.ask('Output directory doesn\'t exist. Create output directory?', True):
|
||||||
os.mkdir(output_path)
|
os.mkdir(output_path)
|
||||||
else:
|
else:
|
||||||
avalon('Aborting configuration generation')
|
Avalon.warning('Aborting configuration generation')
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Iterate through all peers and generate configuration for each peer
|
# Iterate through all peers and generate configuration for each peer
|
||||||
for peer in pm.peers:
|
for peer in pm.peers:
|
||||||
avalon.dbgInfo('Generating configuration file for {}'.format(peer.address))
|
Avalon.dbgInfo('Generating configuration file for {}'.format(peer.address))
|
||||||
with open('{}/{}.conf'.format(output_path, peer.address.split('/')[0]), 'w') as config:
|
with open('{}/{}.conf'.format(output_path, peer.address.split('/')[0]), 'w') as config:
|
||||||
|
|
||||||
# Write Interface configuration
|
# Write Interface configuration
|
||||||
@ -333,7 +333,7 @@ def get_peers_settings():
|
|||||||
Keep enrolling peers until the user aborts.
|
Keep enrolling peers until the user aborts.
|
||||||
"""
|
"""
|
||||||
enroll_peer()
|
enroll_peer()
|
||||||
while avalon.ask('Add new peer?', True):
|
while Avalon.ask('Add new peer?', True):
|
||||||
enroll_peer()
|
enroll_peer()
|
||||||
|
|
||||||
|
|
||||||
@ -341,7 +341,7 @@ def print_help():
|
|||||||
""" Print help messages
|
""" Print help messages
|
||||||
"""
|
"""
|
||||||
help_lines = [
|
help_lines = [
|
||||||
'\n{}Commands are not case-sensitive{}'.format(avalon.FM.BD, avalon.FM.RST),
|
'\n{}Commands are not case-sensitive{}'.format(Avalon.FM.BD, Avalon.FM.RST),
|
||||||
'Interactive // launch interactive shell',
|
'Interactive // launch interactive shell',
|
||||||
'ShowPeers // show all peer information',
|
'ShowPeers // show all peer information',
|
||||||
'LoadProfile [profile path] // load profile from profile_path',
|
'LoadProfile [profile path] // load profile from profile_path',
|
||||||
@ -390,19 +390,19 @@ def command_interpreter(commands):
|
|||||||
elif commands[1].lower() == 'generateconfigs':
|
elif commands[1].lower() == 'generateconfigs':
|
||||||
result = generate_configs(commands[2])
|
result = generate_configs(commands[2])
|
||||||
elif commands[1].lower() == 'exit' or commands[1].lower() == 'quit':
|
elif commands[1].lower() == 'exit' or commands[1].lower() == 'quit':
|
||||||
avalon.warning('Exiting')
|
Avalon.warning('Exiting')
|
||||||
exit(0)
|
exit(0)
|
||||||
elif len(possibilities) > 0:
|
elif len(possibilities) > 0:
|
||||||
avalon.warning('Ambiguous command \"{}\"'.format(commands[1]))
|
Avalon.warning('Ambiguous command \"{}\"'.format(commands[1]))
|
||||||
print('Use \"Help\" command to list available commands')
|
print('Use \"Help\" command to list available commands')
|
||||||
result = 1
|
result = 1
|
||||||
else:
|
else:
|
||||||
avalon.error('Invalid command')
|
Avalon.error('Invalid command')
|
||||||
print('Use \"Help\" command to list available commands')
|
print('Use \"Help\" command to list available commands')
|
||||||
result = 1
|
result = 1
|
||||||
return result
|
return result
|
||||||
except IndexError:
|
except IndexError:
|
||||||
avalon.error('Invalid arguments')
|
Avalon.error('Invalid arguments')
|
||||||
print('Use \"Help\" command to list available commands')
|
print('Use \"Help\" command to list available commands')
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
@ -429,21 +429,21 @@ def main():
|
|||||||
readline.set_completer(completer.complete)
|
readline.set_completer(completer.complete)
|
||||||
readline.parse_and_bind('tab: complete')
|
readline.parse_and_bind('tab: complete')
|
||||||
# Launch interactive trojan shell
|
# Launch interactive trojan shell
|
||||||
prompt = '{}[WGC]> {}'.format(avalon.FM.BD, avalon.FM.RST)
|
prompt = '{}[WGC]> {}'.format(Avalon.FM.BD, Avalon.FM.RST)
|
||||||
while True:
|
while True:
|
||||||
command_interpreter([''] + input(prompt).split(' '))
|
command_interpreter([''] + input(prompt).split(' '))
|
||||||
else:
|
else:
|
||||||
# Return to shell with command return value
|
# Return to shell with command return value
|
||||||
exit(command_interpreter(sys.argv[0:]))
|
exit(command_interpreter(sys.argv[0:]))
|
||||||
except IndexError:
|
except IndexError:
|
||||||
avalon.warning('No commands specified')
|
Avalon.warning('No commands specified')
|
||||||
print_help()
|
print_help()
|
||||||
exit(0)
|
exit(0)
|
||||||
except (KeyboardInterrupt, EOFError):
|
except (KeyboardInterrupt, EOFError):
|
||||||
avalon.warning('Exiting')
|
Avalon.warning('Exiting')
|
||||||
exit(0)
|
exit(0)
|
||||||
except Exception:
|
except Exception:
|
||||||
avalon.error('Exception caught')
|
Avalon.error('Exception caught')
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user