diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b0fb39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv/ +settings.ini \ No newline at end of file diff --git a/README.md b/README.md index dc2c336..9e19619 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,49 @@ # ssh_tunnel_wrapper + wrapper for opening web app using ssh tunnel Wrapper is a tool that users can run on their PC or laptop. It creates an SSH tunnel and opens the web app behind ssh in its window automatically. +## Pyinstaller + +### Linux To compile for Linux (Ubuntu), run: +```shell sudo apt-get install libpython3.12-dev - pip install pyinstaller - pyinstaller --enable-shared --onefile ssh_tunnel_wrapper.py +``` +### Windows -Windows: - +```powershell pyinstaller --hidden-import=babel --hidden-import=babel.numbers ssh_tunnel_wrapper.py +``` -settings.ini format: +## Python venv module -[DEFAULT] +```shell +cd ssh_tunnel_wrapper/ +python3 -m venv .venv/ +.venv/bin/activate +pip3 install -r requirements.txt +``` -ssh_host = ssh_host +## Configuration -ssh_user = ssh_user +Configuration is based on your ```~/.ssh/config``` file. -local_port = local_port +Create file `settings.ini` -remote_host = remote_host # internal IP address behind ssh +```dosini +[DEFAULT] -remote_port = remote_port # port of web app +ssh_host = ssh_host # as defined in ssh_config +local_port = local_port # Port listened on 127.0.0.1 +remote_host = remote_host # internal IP address or hostname +remote_port = remote_port # port of web app -ssh_private_key_path = /home/user1/.ssh/id_rsa +``` diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ca450ea --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +PyQt5 +PyQtWebEngine +sshtunnel +Babel +paramiko \ No newline at end of file diff --git a/settings.ini b/settings.ini deleted file mode 100644 index cc37ef7..0000000 --- a/settings.ini +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -ssh_host = ssh_host -ssh_user = ssh_user -local_port = local_port -remote_host = remote_host -remote_port = remote_port -ssh_private_key_path = /home/user1/.ssh/id_rsa diff --git a/ssh_tunnel_wrapper.py b/ssh_tunnel_wrapper.py index da86e01..17c52cc 100644 --- a/ssh_tunnel_wrapper.py +++ b/ssh_tunnel_wrapper.py @@ -23,36 +23,6 @@ def settings_check_alert(InformativeText): print(f"ssh tunnel wrapper | application version: {formatted_date}") exit(1) -def is_positive_integer(value): - try: - int_value = int(value) - if int_value > 0: - return True - else: - return False - except ValueError: - return False - -def is_valid_ip(ssh_host): - try: - ipaddress.ip_address(ssh_host) - return True - except ValueError: - return False - -def is_valid_private_key(path): - try: - key = paramiko.RSAKey(filename=path) - return True - except paramiko.SSHException: - return False - -def is_valid_unix_username(username): - if re.match(r'^[a-z][a-z0-9_-]{0,31}$', username): - return True - else: - return False - def format_date_now(): suffix = None now = datetime.now() @@ -91,54 +61,12 @@ def load_url(self): config.read('settings.ini') ssh_host = config.get('DEFAULT', 'ssh_host') -ssh_user = config.get('DEFAULT', 'ssh_user') local_port = config.get('DEFAULT', 'local_port') remote_host = config.get('DEFAULT', 'remote_host') remote_port = config.get('DEFAULT', 'remote_port') -ssh_private_key_path = config.get('DEFAULT', 'ssh_private_key_path') - -if ssh_host == 'ssh_host': - settings_check_alert(InformativeText = "The 'ssh_host' in file 'settings.ini' is not set!") -if ssh_user == 'ssh_user': - settings_check_alert(InformativeText = "The 'ssh_user' in file 'settings.ini' is not set!") -if local_port == 'local_port': - settings_check_alert(InformativeText = "The 'local_port' in file 'settings.ini' is not set!") -if remote_host == 'remote_host': - settings_check_alert(InformativeText = "The 'remote_host' in file 'settings.ini' is not set!") -if remote_port == 'remote_port': - settings_check_alert(InformativeText = "The 'remote_port' in file 'settings.ini' is not set!") -if ssh_private_key_path == 'ssh_private_key_path': - settings_check_alert(InformativeText = "The 'ssh_private_key_path' in file 'settings.ini' is not set!") - -if is_positive_integer(local_port): - local_port = int(local_port) -else: - settings_check_alert(InformativeText = "The 'local_port' in file 'settings.ini' must be positive integer!") - -if is_positive_integer(remote_port): - remote_port = int(remote_port) -else: - settings_check_alert(InformativeText = "The 'remote_port' in file 'settings.ini' must be positive integer!") - -if not is_valid_ip(ssh_host): - settings_check_alert(InformativeText = "The 'ssh_host' in file 'settings.ini' must be valid IP address!") - -if not is_valid_ip(remote_host): - settings_check_alert(InformativeText = "The 'remote_host' in file 'settings.ini' must be valid IP address!") - -if not os.path.isfile(ssh_private_key_path): - settings_check_alert(InformativeText = f"The file {ssh_private_key_path} does not exist!") - -if not is_valid_private_key(ssh_private_key_path): - settings_check_alert(InformativeText = f"The file {ssh_private_key_path} should be valid private ssh key!") - -if not is_valid_unix_username(ssh_user): - settings_check_alert(InformativeText = f"The 'ssh_user' should be valid unix username!") with SSHTunnelForwarder( - (ssh_host, 22), - ssh_username=ssh_user, - ssh_private_key=ssh_private_key_path, + ssh_host, remote_bind_address=(remote_host, remote_port), local_bind_address=('127.0.0.1', local_port) ) as tunnel: