raspiblitz/home.admin/config.scripts/internet.sshtunnel.py

275 lines
11 KiB
Python
Raw Normal View History

2019-04-01 22:49:53 +01:00
#!/usr/bin/python3
2019-04-01 23:21:47 +01:00
2020-07-20 16:31:36 +02:00
import re
import subprocess
import sys
2019-04-01 23:31:42 +01:00
# IDEA: At the momemt its just Reverse-SSh Tunnels thats why [INTERNAL-PORT]<[EXTERNAL-PORT]
2019-04-02 22:28:59 +01:00
# For the future also just local ssh tunnels could be added with [INTERNAL-PORT]-[EXTERNAL-PORT]
# for the use case when a server wants to use a RaspiBlitz behind a NAT as Lightning backend
2019-04-02 00:05:37 +01:00
# display config script info
if len(sys.argv) <= 1 or sys.argv[1] == "-h" or sys.argv[1] == "help":
2019-04-01 23:43:21 +01:00
print("forward ports from another server to raspiblitz with reverse SSH tunnel")
2019-12-28 21:32:11 +00:00
print("internet.sshtunnel.py [on|off|restore] [USER]@[SERVER:PORT] \"[INTERNAL-PORT]<[EXTERNAL-PORT]\"")
print("note that [INTERNAL-PORT]<[EXTERNAL-PORT] can one or multiple forwardings")
2019-04-01 23:43:21 +01:00
sys.exit(1)
2019-04-02 01:22:00 +01:00
#
# CONSTANTS
# sudo journalctl -f -u autossh-tunnel
2019-04-02 21:00:39 +01:00
#
2019-04-02 01:22:00 +01:00
2020-07-20 16:31:36 +02:00
SERVICE_NAME = "autossh-tunnel.service"
SERVICE_FILE = "/etc/systemd/system/" + SERVICE_NAME
SERVICE_TEMPLATE = """# see config script internet.sshtunnel.py
2019-04-02 01:22:00 +01:00
[Unit]
Description=AutoSSH tunnel service
After=network.target
[Service]
User=root
Group=root
Environment="AUTOSSH_GATETIME=0"
2019-06-11 19:28:19 +02:00
ExecStart=/usr/bin/autossh -M 0 -N -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ServerAliveCountMax=2 [PLACEHOLDER]
2019-04-02 01:22:00 +01:00
StandardOutput=journal
[Install]
WantedBy=multi-user.target
"""
2019-04-03 02:58:10 +01:00
# get LND port form lnd.conf
2020-07-20 16:31:36 +02:00
LND_PORT = subprocess.getoutput("sudo cat /mnt/hdd/lnd/lnd.conf | grep '^listen=*' | cut -f2 -d':'")
if len(LND_PORT) == 0:
LND_PORT = "9735"
2019-04-03 02:58:10 +01:00
2019-04-28 02:42:44 +02:00
2020-07-20 16:31:36 +02:00
#######################
2019-04-02 00:05:37 +01:00
# SWITCHING ON
2020-07-20 16:31:36 +02:00
#######################
def on(restore_on_update=False):
forwarding_lnd = False
2019-04-02 00:05:37 +01:00
2019-04-02 01:22:00 +01:00
# check if already running
2020-07-20 16:31:36 +02:00
is_running = subprocess.getoutput("sudo systemctl --no-pager | grep -c '{}'".format(SERVICE_NAME))
if int(is_running) > 0:
print("SSH TUNNEL SERVICE IS RUNNING - run 'internet.sshtunnel.py off' first to set new tunnel")
sys.exit(1)
2019-04-02 01:22:00 +01:00
# check server address
2019-04-02 01:53:28 +01:00
if len(sys.argv) < 3:
2019-12-28 21:32:11 +00:00
print("[USER]@[SERVER:PORT] missing - use 'internet.sshtunnel.py -h' for help")
2019-04-02 01:53:28 +01:00
sys.exit(1)
if sys.argv[2].count("@") != 1:
2019-12-28 21:32:11 +00:00
print("[USER]@[SERVER:PORT] wrong - use 'internet.sshtunnel.py -h' for help")
2019-04-02 01:22:00 +01:00
sys.exit(1)
2019-04-02 01:53:28 +01:00
ssh_server = sys.argv[2]
2019-12-28 21:32:11 +00:00
if ssh_server.count(":") == 0:
ssh_server_host = ssh_server
ssh_server_port = "22"
elif ssh_server.count(":") == 1:
ssh_server_split = ssh_server.split(":")
ssh_server_host = ssh_server_split[0]
ssh_server_port = ssh_server_split[1]
else:
print("[USER]@[SERVER:PORT] wrong - use 'internet.sshtunnel.py -h' for help")
2020-07-20 16:31:36 +02:00
sys.exit(1)
2019-04-02 01:22:00 +01:00
2020-07-20 16:31:36 +02:00
# generate additional parameter for autossh (forwarding ports)
2019-04-02 01:22:00 +01:00
if len(sys.argv) < 4:
2019-04-02 22:28:59 +01:00
print("[INTERNAL-PORT]<[EXTERNAL-PORT] missing")
2019-04-02 00:05:37 +01:00
sys.exit(1)
2020-07-20 16:31:36 +02:00
ssh_ports = ""
additional_parameters = ""
2019-04-02 01:22:00 +01:00
i = 3
while i < len(sys.argv):
# check forwarding format
if sys.argv[i].count("<") != 1:
print("[INTERNAL-PORT]<[EXTERNAL-PORT] wrong format '%s'" % (sys.argv[i]))
2019-04-02 01:22:00 +01:00
sys.exit(1)
# get ports
2020-07-20 16:31:36 +02:00
sys.argv[i] = re.sub('"', '', sys.argv[i])
2019-04-03 19:05:51 +01:00
ports = sys.argv[i].split("<")
2019-04-02 01:22:00 +01:00
port_internal = ports[0]
port_external = ports[1]
2020-07-20 16:31:36 +02:00
if not port_internal.isdigit():
print("[INTERNAL-PORT]<[EXTERNAL-PORT] internal not number '%s'" % (sys.argv[i]))
2019-04-02 01:22:00 +01:00
sys.exit(1)
2020-07-20 16:31:36 +02:00
if not port_external.isdigit():
print("[INTERNAL-PORT]<[EXTERNAL-PORT] external not number '%s'" % (sys.argv[i]))
2020-07-20 16:31:36 +02:00
sys.exit(1)
if port_internal == LND_PORT:
2019-04-28 04:14:42 +02:00
print("Detected LND Port Forwarding")
2020-07-20 16:31:36 +02:00
forwarding_lnd = True
2019-04-03 02:58:10 +01:00
if port_internal != port_external:
2020-07-20 16:31:36 +02:00
print("FAIL: When tunneling your local LND port "
"'{}' it needs to be the same on the external server, but is '{}'".format(LND_PORT,
port_external))
print(
"Try again by using the same port. If you cant change the external port, "
"change local LND port with: /home/admin/config.scripts/lnd.setport.sh")
2019-04-03 02:58:10 +01:00
sys.exit(1)
2019-04-02 01:22:00 +01:00
2019-04-02 22:28:59 +01:00
ssh_ports = ssh_ports + "\"%s\" " % (sys.argv[i])
2020-07-20 16:31:36 +02:00
additional_parameters = additional_parameters + "-R %s:localhost:%s " % (port_external, port_internal)
2019-12-28 21:32:11 +00:00
i = i + 1
2019-04-02 01:22:00 +01:00
2020-07-20 16:31:36 +02:00
# generate additional parameter for autossh (server)
2019-04-02 22:28:59 +01:00
ssh_ports = ssh_ports.strip()
2020-07-20 16:31:36 +02:00
additional_parameters = additional_parameters + "-p " + ssh_server_port + " " + ssh_server_host
2019-04-02 01:22:00 +01:00
# generate custom service config
2020-07-20 16:31:36 +02:00
service_data = SERVICE_TEMPLATE.replace("[PLACEHOLDER]", additional_parameters)
2019-04-02 01:22:00 +01:00
2019-04-02 03:22:00 +01:00
# debug print out service
2019-04-02 02:54:30 +01:00
print()
2020-07-20 16:31:36 +02:00
print("*** New systemd service: {}".format(SERVICE_NAME))
2019-04-02 01:22:00 +01:00
print(service_data)
# write service file
2019-04-02 03:48:57 +01:00
service_file = open("/home/admin/temp.service", "w")
2019-04-02 01:22:00 +01:00
service_file.write(service_data)
service_file.close()
2020-07-20 16:31:36 +02:00
subprocess.call("sudo mv /home/admin/temp.service {}".format(SERVICE_FILE), shell=True)
2019-04-02 01:22:00 +01:00
2019-04-02 02:54:30 +01:00
# check if SSH keys for root user need to be created
print()
2019-04-02 03:33:04 +01:00
print("*** Checking root SSH pub keys")
2019-04-02 03:27:52 +01:00
try:
2019-04-02 03:33:04 +01:00
ssh_pubkey = subprocess.check_output("sudo cat /root/.ssh/id_rsa.pub", shell=True, universal_newlines=True)
2019-04-02 03:27:52 +01:00
print("OK - root id_rsa.pub file exists")
2020-07-20 16:31:36 +02:00
except subprocess.CalledProcessError:
2019-04-02 02:54:30 +01:00
print("Generating root SSH keys ...")
2020-07-20 16:31:36 +02:00
subprocess.call("sudo sh -c 'yes y | sudo -u root ssh-keygen -b 2048 -t rsa -f ~/.ssh/id_rsa -q -N \"\"'",
shell=True)
2019-04-02 03:33:04 +01:00
ssh_pubkey = subprocess.check_output("sudo cat /root/.ssh/id_rsa.pub", shell=True, universal_newlines=True)
2020-07-20 16:31:36 +02:00
2019-04-02 19:16:37 +01:00
# copy SSH keys for backup (for update with new sd card)
print("making backup copy of SSH keys")
subprocess.call("sudo cp -r /root/.ssh /mnt/hdd/ssh/root_backup", shell=True)
print("DONE")
2020-07-20 16:31:36 +02:00
2019-04-02 19:16:37 +01:00
# write ssh tunnel data to raspiblitz config (for update with new sd card)
print("*** Updating RaspiBlitz Config")
with open('/mnt/hdd/raspiblitz.conf') as f:
file_content = f.read()
if file_content.count("sshtunnel=") == 0:
2020-07-20 16:31:36 +02:00
file_content = file_content + "\nsshtunnel=''"
2019-04-02 19:16:37 +01:00
file_content = re.sub("sshtunnel=.*", "sshtunnel='%s %s'" % (ssh_server, ssh_ports), file_content)
2019-04-28 02:06:13 +02:00
2020-07-20 16:31:36 +02:00
if not restore_on_update:
server_domain = ssh_server.split("@")[1]
ssh_server = server_domain
2019-12-29 17:37:19 +00:00
if ssh_server.count(":") == 0:
ssh_server_host = ssh_server
2020-07-20 16:31:36 +02:00
ssh_server_port = "22" # ToDo(frennkie) this is not used
2019-12-29 17:37:19 +00:00
elif ssh_server.count(":") == 1:
ssh_server_split = ssh_server.split(":")
ssh_server_host = ssh_server_split[0]
2020-07-20 16:31:36 +02:00
ssh_server_port = ssh_server_split[1] # ToDo(frennkie) this is not used
2019-12-29 17:37:19 +00:00
else:
print("syntax error!")
sys.exit(1)
2020-07-20 16:31:36 +02:00
# make sure server_domain is set as tls alias
2019-04-28 02:06:13 +02:00
print("Setting server as tls alias")
2020-07-20 16:31:36 +02:00
old_config_hash = subprocess.getoutput("sudo shasum -a 256 /mnt/hdd/lnd/lnd.conf")
2019-04-03 14:35:37 +01:00
subprocess.call("sudo sed -i \"s/^#tlsextradomain=.*/tlsextradomain=/g\" /mnt/hdd/lnd/lnd.conf", shell=True)
2020-07-20 16:31:36 +02:00
subprocess.call(
"sudo sed -i \"s/^tlsextradomain=.*/tlsextradomain={}/g\" /mnt/hdd/lnd/lnd.conf".format(ssh_server_host),
shell=True)
new_config_hash = subprocess.getoutput("sudo shasum -a 256 /mnt/hdd/lnd/lnd.conf")
if old_config_hash != new_config_hash:
2019-04-28 02:06:13 +02:00
print("lnd.conf changed ... generating new TLS cert")
2020-07-20 16:31:36 +02:00
subprocess.call("sudo /home/admin/config.scripts/lnd.tlscert.sh refresh", shell=True)
2019-04-28 02:06:13 +02:00
else:
print("lnd.conf unchanged... keep TLS cert")
2020-07-20 16:31:36 +02:00
if forwarding_lnd:
2019-04-03 03:48:35 +01:00
# setting server explicitly on LND if LND port is forwarded
2019-04-28 04:43:11 +02:00
print("Setting fixed address for LND with raspiblitz lndAddress")
2020-07-20 16:31:36 +02:00
file_content = re.sub("lndAddress=.*", "lndAddress='{}'".format(ssh_server_host), file_content)
2019-04-08 02:10:25 +01:00
else:
2019-04-28 04:43:11 +02:00
print("No need to set fixed address for LND with raspiblitz lndAddress")
2019-04-02 22:38:26 +01:00
file_content = "".join([s for s in file_content.splitlines(True) if s.strip("\r\n")]) + "\n"
2019-04-02 19:16:37 +01:00
print(file_content)
with open("/mnt/hdd/raspiblitz.conf", "w") as text_file:
2019-04-02 22:38:26 +01:00
text_file.write(file_content)
2019-04-02 19:16:37 +01:00
print("DONE")
2019-04-02 02:54:30 +01:00
# make sure autossh is installed
# https://www.everythingcli.org/ssh-tunnelling-for-fun-and-profit-autossh/
print()
print("*** Install autossh")
subprocess.call("sudo apt-get install -y autossh", shell=True)
2020-07-20 16:31:36 +02:00
2019-04-02 01:22:00 +01:00
# enable service
print()
2020-07-20 16:31:36 +02:00
print("*** Enabling systemd service: {}".format(SERVICE_NAME))
2019-04-02 02:54:30 +01:00
subprocess.call("sudo systemctl daemon-reload", shell=True)
2020-07-20 16:31:36 +02:00
subprocess.call("sudo systemctl enable {}".format(SERVICE_NAME), shell=True)
2019-04-02 01:22:00 +01:00
# final info (can be ignored if run by other script)
2019-04-02 02:54:30 +01:00
print()
2019-04-02 22:38:26 +01:00
print("**************************************")
print("*** WIN - SSH TUNNEL SERVICE SETUP ***")
print("**************************************")
2019-04-02 03:50:08 +01:00
print("See chapter 'How to setup port-forwarding with a SSH tunnel?' in:")
2019-04-02 02:54:30 +01:00
print("https://github.com/rootzoll/raspiblitz/blob/master/FAQ.md")
2019-04-02 01:42:25 +01:00
print("- Tunnel service needs final reboot to start.")
2020-07-20 16:31:36 +02:00
print("- After reboot check logs: sudo journalctl -f -u {}".format(SERVICE_NAME))
print("- Make sure the SSH pub key of this RaspiBlitz is in 'authorized_keys' of {}:".format(ssh_server_host))
2019-04-02 02:54:30 +01:00
print(ssh_pubkey)
print()
2019-04-02 00:05:37 +01:00
2020-07-20 16:31:36 +02:00
#######################
# SWITCHING OFF
#######################
def off():
print("*** Disabling systemd service: {}".format(SERVICE_NAME))
subprocess.call("sudo systemctl stop {}".format(SERVICE_NAME), shell=True)
subprocess.call("sudo systemctl disable {}".format(SERVICE_NAME), shell=True)
2019-04-28 02:42:44 +02:00
subprocess.call("sudo systemctl reset-failed", shell=True)
2020-07-20 16:31:36 +02:00
subprocess.call("sudo rm {}".format(SERVICE_FILE), shell=True)
2019-04-02 02:54:30 +01:00
subprocess.call("sudo systemctl daemon-reload", shell=True)
print("OK Done")
print()
2019-04-02 00:05:37 +01:00
2019-04-03 03:48:35 +01:00
print("*** Removing LND Address")
2019-04-03 15:06:52 +01:00
subprocess.call("sudo /home/admin/config.scripts/lnd.setaddress.sh off", shell=True)
2019-04-03 03:48:35 +01:00
print()
2019-04-02 19:16:37 +01:00
print("*** Removing SSH Tunnel data from RaspiBlitz config")
with open('/mnt/hdd/raspiblitz.conf') as f:
file_content = f.read()
file_content = re.sub("sshtunnel=.*", "", file_content)
file_content = re.sub("\n\n", "\n", file_content)
print(file_content)
with open("/mnt/hdd/raspiblitz.conf", "w") as text_file:
text_file.write(file_content)
print("OK Done")
2019-04-02 00:05:37 +01:00
2020-07-20 16:31:36 +02:00
def main():
if sys.argv[1] == "restore":
print("internet.sshtunnel.py -> running with restore flag")
on(restore_on_update=True)
elif sys.argv[1] == "on":
on()
elif sys.argv[1] == "off":
off()
else:
# UNKNOWN PARAMETER
print("unknown parameter - use 'internet.sshtunnel.py -h' for help")
if __name__ == '__main__':
main()