Browse Source

merge of dev and sshtunnel

master
Christian Rotzoll 6 years ago
parent
commit
8ae5611364
  1. 59
      FAQ.md
  2. 3
      README.md
  3. 2
      build_sdcard.sh
  4. 2
      home.admin/40addHDD.sh
  5. 4
      home.admin/50copyHDD.sh
  6. 24
      home.admin/97addMobileWallet.sh
  7. 41
      home.admin/97addMobileWalletShango.sh
  8. 52
      home.admin/97addMobileWalletZap.sh
  9. 13
      home.admin/_background.sh
  10. 79
      home.admin/_bootstrap.provision.sh
  11. 77
      home.admin/_bootstrap.sh
  12. 2
      home.admin/assets/lnd.service
  13. 231
      home.admin/config.scripts/internet.sshtunnel.py
  14. 83
      home.admin/config.scripts/lnd.setaddress.sh
  15. 2
      home.admin/config.scripts/lnd.setname.sh
  16. 13
      home.admin/config.scripts/lnd.setport.sh

59
FAQ.md

@ -624,3 +624,62 @@ If that not works ry to ping the IP of the RaspiBlitz with `ping [IP-of-RaspiBli
- Some Routers have `IP Isolation` switched on - not allowing to devices to connect
If that all is not working: Join the conversation on [GitHub Issue #420](https://github.com/rootzoll/raspiblitz/issues/420).
## How to setup port-forwarding with a SSH tunnel?
To use a public server for port-forwarding thru a SSH tunnel you can use the following experimental script on the RaspiBlitz (since v1.2):
`/home/admin/config.scripts/internet.sshtunnel.py`
But first you need to make sure that the public server you are using is supporting SSH reverse tunneling and authentification by public authorized key. Check the `/etc/ssh/sshd_config` on the public server to contain the following settings:
```
RSAAuthentication yes
PubkeyAuthentication yes
GatewayPorts yes
AllowTcpForwarding yes
```
You can add those at the end of the file, save and reboot.
On the RaspiBlitz you can then setup for example to forward the gRPC port 10009 (internal port) to the port 20009 on the public server (external port) with the user = `test` and server address = `raspiblitz.com` with the following command:
`/home/admin/config.scripts/internet.sshtunnel.py on test@raspiblitz.com "10009<20009"`
You can even set multiple port forwardings like with:
`/home/admin/config.scripts/internet.sshtunnel.py on test@raspiblitz.com "10009<20009" "8080<9090"`
Please beware that after you set such a port forwarding you need to set the domain of the public server as a `DynamicDNS` name (leave update url empty) and then connect mobile wallets fresh or export again the macaroons/certs. When connecting the mobile wallets you may need to adjust ports manually after QR code scan. And if you SSH tunnel the LND node port `9735` you may also need to sun the custom LND port script and maybe also a manual set of the domain in the LND service is needed. This all is very experimental at the moment ... better integration will come in the future.
To switch this SSH tunneling off again use:
`/home/admin/config.scripts/internet.sshtunnel.py off` and also deactivate the DynamicDNS again.
## How to setup just a port-forwarding user on my public server?
Make sure the `/etc/ssh/sshd_config` has the following lines at the end:
```
RSAAuthentication yes
PubkeyAuthentication yes
GatewayPorts yes
AllowTcpForwarding yes
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
```
The last one stores all authorized_keys in one directory with a file per user. See https://serverfault.com/questions/313465/is-a-central-location-for-authorized-keys-a-good-idea#424659 To prepare this run:
```
mkdir /etc/ssh/authorized_keys
groupadd forwardings
```
To add a forwarding user run:
```
useradd -g forwardings -d /home [USERNAME]
echo "command="date" [CONTENT-OF-RASPIBLITZ-ROOT-SSH-PUBKEY]" > /etc/ssh/authorized_keys/[USERNAME]
passwd [USERNAME]
```
The `[CONTENT-OF-RASPIBLITZ-ROOT-SSH-PUBKEY]` you get when running the `internet.sshtunnel.py` script on the RaspiBlitz (see above).

3
README.md

@ -385,11 +385,14 @@ To do so you can register at an DynamicDomain service like freedns.afraid.org an
* 8333 (Bitcoin/mainnet)
* 9735 (LND Node)
* 10009 (LND RPC)
* 8080 (LND REST API)
... from your internet router to the local IP of your RaspiBlitz and then activate unter "Services" the "DynamicDNS" option.
You will be asked for your dynamic domain name such like "mynode.crabdance.org" and you can also optionally set an URL that will be called regularly to update your routers IP with the dynnamic domain service. At freedns.afraid.org this URL is called "Direct URL" under the menu "Dynamic DNS" once you added one.
*NOTE: DynamicDNS just works if you can forward ports on your router and you have a temporary public IP address (your ISP is not running you behind a NAT - like on most mobile connections). Another solution to make your ports reachable from the public internet is to use reverse ssh tunneling - see FAQ on ['How to setup port-forwarding with a SSH tunnel?'](FAQ.md#how-to-setup-port-forwarding-with-a-ssh-tunnel)*
##### Run behind TOR
You can run your Bitcoin- and Lightning-Node as a TOR hidden service - replacing your IP with an .onion-address

2
build_sdcard.sh

@ -245,6 +245,8 @@ sudo apt-get install -y vnstat
# prepare for BTRFS data drive raid
sudo apt-get install -y btrfs-tools
# prepare for ssh reverse tunneling
sudo apt-get install -y autossh
# prepare for display graphics mode
# see https://github.com/rootzoll/raspiblitz/pull/334

2
home.admin/40addHDD.sh

@ -87,7 +87,7 @@ if [ ${existsHDD} -gt 0 ]; then
echo "WARNING: No publicIP information at all yet - working with placeholder : ${localIP}"
freshPublicIP="${localIP}"
fi
echo "publicIP=${freshPublicIP}" >> $configFile
echo "publicIP='${freshPublicIP}'" >> $configFile
fi

4
home.admin/50copyHDD.sh

@ -111,8 +111,8 @@ if [ ${count} -gt 0 ]; then
echo "Found data in /mnt/hdd/bitcoin/indexes/txindex"
anyDataAtAll=1
fi
if [ ${count} -lt 1500 ]; then
echo "FAIL: less then 1500 .ldb files (${count}) in /mnt/hdd/bitcoin/indexes/txindex (transfere seems invalid)"
if [ ${count} -lt 500 ]; then
echo "FAIL: less then 500 .ldb files (${count}) in /mnt/hdd/bitcoin/indexes/txindex (transfere seems invalid)"
quickCheckOK=0
fi

24
home.admin/97addMobileWallet.sh

@ -4,19 +4,37 @@
source /home/admin/raspiblitz.info
source /mnt/hdd/raspiblitz.conf
justLocal=1
# if dynDomain is set connect from outside is possible (no notice)
if [ ${#dynDomain} -gt 0 ]; then
justLocal=0
fi
# if sshtunnel to 10009/8080 then outside reach is possible (no notice)
isForwarded=$(echo ${sshtunnel} | grep -c "10009<")
if [ ${isForwarded} -gt 0 ]; then
justLocal=0
fi
isForwarded=$(echo ${sshtunnel} | grep -c "8080<")
if [ ${isForwarded} -gt 0 ]; then
justLocal=0
fi
# check if dynamic domain is set
if [ ${#dynDomain} -eq 0 ]; then
if [ ${justLocal} -eq 1 ]; then
whiptail --title " Just Local Network? " --yesno "If you want to connect with your RaspiBlitz
also from outside your local network you need to
activate 'Services' -> 'DynamicDNS' FIRST.
Or use SSH tunnel forwarding for port 10009.
For more details see chapter in GitHub README
'Public Domain with DynamicDNS'
on the service 'DynamicDNS'
https://github.com/rootzoll/raspiblitz
Do you JUST want to connect with your mobile
when your are on the same LOCAL NETWORK?
" 14 54
" 15 54
response=$?
case $response in
1) exit ;;

41
home.admin/97addMobileWalletShango.sh

@ -6,19 +6,46 @@ source /mnt/hdd/raspiblitz.conf
clear
# get local IP
myip=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
# default host to local IP & port 10009
host=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
port="10009"
# replace dyndomain if available
# change host to dynDNS if set
if [ ${#dynDomain} -gt 0 ]; then
myip="${dynDomain}"
host="${dynDomain}"
echo "port 10009 forwarding from dynDomain ${host}"
fi
#echo -e "${myip}:10009,\n$(xxd -p -c2000 ./.lnd/data/chain/${network}/${chain}net/admin.macaroon)," > qr.txt && cat ./.lnd/tls.cert >>qr.txt
echo -e "${myip}:10009,\n$(xxd -p -c2000 ./.lnd/data/chain/${network}/${chain}net/admin.macaroon)," > qr.txt
# check if port 10009 is forwarded
if [ ${#sshtunnel} -gt 0 ]; then
isForwarded=$(echo ${sshtunnel} | grep -c "10009<")
if [ ${isForwarded} -gt 0 ]; then
host=$(echo $sshtunnel | cut -d '@' -f2 | cut -d ' ' -f1)
port=$(echo $sshtunnel | awk '{split($0,a,"10009<"); print a[2]}' | cut -d ' ' -f1 | sed 's/[^0-9]//g')
echo "port 10009 forwarding from port ${port} from server ${host}"
else
echo "port 10009 is not part of the ssh forwarding - keep default port 10009"
fi
fi
# write qr code data to text file
echo -e "${host}:${port},\n$(xxd -p -c2000 ./.lnd/data/chain/${network}/${chain}net/admin.macaroon)," > qr.txt
# display qr code
./XXdisplayQRlcd.sh
#clear
#echo "******************************"
#echo "Connect Shango Mobile Wallet"
#echo "******************************"
#echo ""
#echo "GETTING THE APP"
#echo "At the moment this app is in public beta testing:"
#echo "iOS: Read https://testflight.apple.com/join/WwCjFnS8 (open on device)"
#echo "Android: https://play.google.com/apps/testing/com.shango (open on device)"
#echo ""
#echo "*** STEP 1 ***"
msg=""
if [ ${#dynDomain} -eq 0 ]; then
msg="Once you have the app is running make sure you are on the same local network (WLAN same as LAN)."
@ -34,6 +61,7 @@ whiptail --backtitle "Connecting Shango Mobile Wallet" \
if [ $? -eq 0 ]; then
/home/admin/XXdisplayQR.sh
fi
shred qr.txt
rm -f qr.txt
@ -41,6 +69,7 @@ whiptail --backtitle "Connecting Shango Mobile Wallet" \
--title "Press Connect on Shango" \
--msgbox "Now press 'Connect' within the Shango Wallet.\n\nIf its not working - check issues on GitHub:\n\nhttps://github.com/neogeno/shango-lightning-wallet/issues" 15 65
# clean up
./XXdisplayQRlcd_hide.sh
shred qr.png 2> /dev/null
rm -f qr.png

52
home.admin/97addMobileWalletZap.sh

@ -55,6 +55,31 @@ make
cd
sleep 3
# default host to local IP and port 10009
local=1
host=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
port="10009"
# change host to dynDNS if set
if [ ${#dynDomain} -gt 0 ]; then
local=0
host="${dynDomain}"
echo "port 10009 forwarding from dynDomain ${host}"
fi
# check if port 10009 is forwarded
if [ ${#sshtunnel} -gt 0 ]; then
isForwarded=$(echo ${sshtunnel} | grep -c "10009<")
if [ ${isForwarded} -gt 0 ]; then
local=0
host=$(echo $sshtunnel | cut -d '@' -f2 | cut -d ' ' -f1)
port=$(echo $sshtunnel | awk '{split($0,a,"10009<"); print a[2]}' | cut -d ' ' -f1 | sed 's/[^0-9]//g')
echo "port 10009 forwarding from port ${port} from server ${host}"
else
echo "port 10009 is not part of the ssh forwarding - keep default port 10009"
fi
fi
clear
echo "******************************"
echo "Connect Zap Mobile Wallet"
@ -66,7 +91,7 @@ echo "1. Install the app 'TestFlight' from Apple Appstore. Open it and agree to
echo "2. Open on your iOS device https://github.com/LN-Zap/zap-iOS and follow 'Download the Alpha'"
echo ""
echo "*** PAIRING STEP 1 ***"
if [ ${#dynDomain} -eq 0 ]; then
if [ ${local} -eq 1 ]; then
echo "Once you have the app is running make sure you are on the same local network (WLAN same as LAN)."
fi
echo "During Setup of the Zap app you should get to the 'Connect Remote-Node' screen."
@ -79,29 +104,8 @@ read key
clear
echo "*** PAIRING STEP 2 : Click on Scan (make whole QR code fill camera) ***"
if [ ${#dynDomain} -eq 0 ]; then
# If you drop the -i parameter, lndconnect will use the external IP.
lndconnect -i
else
# when dynamic domain is set
lndconnect --host=${dynDomain}
fi
platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
platform='linux'
elif [[ "$unamestr" == 'Darwin' ]]; then
platform='Darwin' # mac OSX
fi
if [[ $platform == 'Linux' ]]; then
echo "(To shrink QR code: CTRL-) Press ENTER when finished."
elif [[ $platform == 'Darwin' ]]; then
echo "(To shrink QR code: CMD-) Press ENTER when finished."
fi
lndconnect --host=${host} --port=${port}
echo "(To shrink QR code: CTRL- or CMD-) Press ENTER when finished."
read key
clear

13
home.admin/_background.sh

@ -87,6 +87,10 @@ do
# every 15min - not too often
# because its a ping to external service
recheckPublicIP=$((($counter % 900)+1))
# prevent when lndAddress is set
if [ ${#lndAddress} -gt 3 ]; then
recheckPublicIP=0
fi
updateDynDomain=0
if [ ${recheckPublicIP} -eq 1 ]; then
echo "*** RECHECK PUBLIC IP ***"
@ -120,8 +124,8 @@ do
# 1) update config file
echo "update config value"
sed -i "s/^publicIP=.*/publicIP=${freshPublicIP}/g" ${configFile}
publicIP=${freshPublicIP}
sed -i "s/^publicIP=.*/publicIP='${freshPublicIP}'/g" ${configFile}
publicIP='${freshPublicIP}'
# 2) only restart LND if dynDNS is activated
# because this signals that user wants "public node"
@ -165,11 +169,8 @@ do
passwordC=$(sudo cat /root/lnd.autounlock.pwd)
command="sudo python /home/admin/config.scripts/lnd.unlock.py '${passwordC}'"
bash -c "${command}"
else
echo "lncli says not locked"
fi
else
echo "auto-unlock is OFF"
fi
fi

79
home.admin/_bootstrap.provision.sh

@ -82,18 +82,25 @@ sed -i "6s/.*/After=${network}d.service/" /home/admin/assets/lnd.service >> ${lo
sudo cp /home/admin/assets/lnd.service /etc/systemd/system/lnd.service >> ${logFile} 2>&1
sudo chmod +x /etc/systemd/system/lnd.service >> ${logFile} 2>&1
# backup LND dir (especially for macaroons and tlscerts)
# https://github.com/rootzoll/raspiblitz/issues/324
echo "*** Make backup of LND directory" >> ${logFile}
sudo rm -r /mnt/hdd/backup_lnd
sudo cp -r /mnt/hdd/lnd /mnt/hdd/backup_lnd >> ${logFile} 2>&1
numOfDiffers=$(sudo diff -arq /mnt/hdd/lnd /mnt/hdd/backup_lnd | grep -c "differ")
if [ ${numOfDiffers} -gt 0 ]; then
echo "FAIL: Backup was not successfull" >> ${logFile}
sudo diff -arq /mnt/hdd/lnd /mnt/hdd/backup_lnd >> ${logFile} 2>&1
echo "removing backup dir to prevent false override" >> ${logFile}
else
echo "OK Backup is valid." >> ${logFile}
fi
echo "" >> ${logFile}
# finish setup (SWAP, Benus, Firewall, Update, ..)
sudo sed -i "s/^message=.*/message='Setup System ..'/g" ${infoFile}
/home/admin/90finishSetup.sh >> ${logFile} 2>&1
# set the local network hostname
if [ ${#hostname} -gt 0 ]; then
echo "Setting new network hostname '$hostname'" >> ${logFile}
sudo raspi-config nonint do_hostname ${hostname} >> ${logFile} 2>&1
else
echo "No hostname set." >> ${logFile}
fi
##########################
# PROVISIONING SERVICES
##########################
@ -158,7 +165,9 @@ fi
# CUSTOM PORT
echo "Provisioning LND Port" >> ${logFile}
lndPort=$(sudo cat /mnt/hdd/lnd/lnd.conf | grep "^listen=*" | cut -f2 -d':')
if [ ${#lndPort} -eq 0 ]; then
lndPort=$(sudo cat /mnt/hdd/lnd/lnd.conf | grep "^listen=*" | cut -f2 -d':')
fi
if [ ${#lndPort} -gt 0 ]; then
if [ "${lndPort}" != "9735" ]; then
echo "User is running custom LND port: ${lndPort}" >> ${logFile}
@ -170,8 +179,60 @@ else
echo "Was not able to get LND port from config." >> ${logFile}
fi
# ROOT SSH KEYS
# check if a backup on HDD exists and when retsore back
backupRootSSH=$(sudo ls /mnt/hdd/ssh/root_backup 2>/dev/null | grep -c "id_rsa")
if [ ${backupRootSSH} -gt 0 ]; then
echo "Provisioning Root SSH Keys - RESTORING from HDD" >> ${logFile}
sudo cp -r /mnt/hdd/ssh/root_backup /root/.ssh
sudo chown -R root:root /root/.ssh
else
echo "Provisioning Root SSH Keys - keep default" >> ${logFile}
fi
# SSH TUNNEL
if [ "${#sshtunnel}" -gt 0 ]; then
echo "Provisioning SSH Tunnel - run config script" >> ${logFile}
sudo sed -i "s/^message=.*/message='Setup SSH Tunnel'/g" ${infoFile}
sudo /home/admin/config.scripts/internet.sshtunnel.py restore ${sshtunnel} >> ${logFile} 2>&1
else
echo "Provisioning SSH Tunnel - not active" >> ${logFile}
fi
# replay backup LND dir (especially for macaroons and tlscerts)
# https://github.com/rootzoll/raspiblitz/issues/324
echo "" >> ${logFile}
echo "*** Replay backup of LND directory" >> ${logFile}
if [ -d "/mnt/hdd/backup_lnd" ]; then
echo "Copying ..." >> ${logFile}
sudo cp -r /mnt/hdd/backup_lnd /mnt/hdd/lnd >> ${logFile} 2>&1
echo "Updating user admin creds ..." >> ${logFile}
sudo cp /mnt/hdd/lnd/lnd.conf /home/admin/.lnd/lnd.conf >> ${logFile} 2>&1
sudo cp /mnt/hdd/lnd/tls.cert /home/admin/.lnd/tls.cert >> ${logFile} 2>&1
sudo cp -r /mnt/hdd/lnd/data/chain /home/admin/.lnd/data/chain >> ${logFile} 2>&1
sudo chown -R admin:admin /home/admin/.lnd >> ${logFile} 2>&1
echo "DONE" >> ${logFile}
else
echo "No BackupDir so skipping that step." >> ${logFile}
fi
echo "" >> ${logFile}
sudo sed -i "s/^message=.*/message='Setup Done'/g" ${infoFile}
# set the local network hostname
# have at the end - see https://github.com/rootzoll/raspiblitz/issues/462
if [ ${#hostname} -gt 0 ]; then
hostnameSanatized=$(echo "${hostname}"| tr -dc '[:alnum:]\n\r')
if [ ${#hostnameSanatized} -gt 0 ]; then
echo "Setting new network hostname '$hostnameSanatized'" >> ${logFile}
sudo raspi-config nonint do_hostname ${hostnameSanatized} >> ${logFile} 2>&1
else
echo "WARNING: hostname in raspiblitz.conf contains just special chars" >> ${logFile}
fi
else
echo "No hostname set." >> ${logFile}
fi
echo "DONE - Give raspi some cool off time after hard building .... 20 secs sleep" >> ${logFile}
sleep 20

77
home.admin/_bootstrap.sh

@ -302,38 +302,65 @@ echo "Check if HDD contains configuration .." >> $logFile
configExists=$(ls ${configFile} | grep -c '.conf')
if [ ${configExists} -eq 1 ]; then
# make sure lndAddress & lndPort exist
valueExists=$(cat ${configFile} | grep -c 'lndPort=')
if [ ${valueExists} -eq 0 ]; then
lndPort=$(sudo cat /mnt/hdd/lnd/lnd.conf | grep "^listen=*" | cut -f2 -d':')
if [ ${#lndPort} -eq 0 ]; then
lndPort="9735"
fi
echo "lndPort='${lndPort}'" >> ${configFile}
fi
valueExists=$(cat ${configFile} | grep -c 'lndAddress=')
if [ ${valueExists} -eq 0 ]; then
echo "lndAddress=''" >> ${configFile}
fi
# load values
echo "load and update publicIP" >> $logFile
source ${configFile}
freshPublicIP=""
# determine the publicIP/domain that LND should announce
if [ ${#lndAddress} -gt 3 ]; then
# use domain as PUBLICIP
freshPublicIP="${lndAddress}"
# update public IP on boot
# wait otherwise looking for publicIP fails
sleep 5
freshPublicIP=$(curl -s http://v4.ipv6-test.com/api/myip.php)
# sanity check on IP data
# see https://github.com/rootzoll/raspiblitz/issues/371#issuecomment-472416349
echo "-> sanity check of IP data: ${freshPublicIP}"
if [[ $freshPublicIP =~ ^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$ ]]; then
echo "OK IPv6"
elif [[ $freshPublicIP =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]; then
echo "OK IPv4"
else
echo "FAIL - not an IPv4 or IPv6 address"
freshPublicIP=""
fi
if [ ${#freshPublicIP} -eq 0 ]; then
# prevent having no publicIP set at all and LND getting stuck
# https://github.com/rootzoll/raspiblitz/issues/312#issuecomment-462675101
if [ ${#publicIP} -eq 0 ]; then
localIP=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
echo "WARNING: No publicIP information at all - working with placeholder: ${localIP}" >> $logFile
freshPublicIP="${localIP}"
# update public IP on boot
# wait otherwise looking for publicIP fails
sleep 5
freshPublicIP=$(curl -s http://v4.ipv6-test.com/api/myip.php)
# sanity check on IP data
# see https://github.com/rootzoll/raspiblitz/issues/371#issuecomment-472416349
echo "-> sanity check of IP data: ${freshPublicIP}"
if [[ $freshPublicIP =~ ^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$ ]]; then
echo "OK IPv6"
elif [[ $freshPublicIP =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]]; then
echo "OK IPv4"
else
echo "FAIL - not an IPv4 or IPv6 address"
freshPublicIP=""
fi
if [ ${#freshPublicIP} -eq 0 ]; then
# prevent having no publicIP set at all and LND getting stuck
# https://github.com/rootzoll/raspiblitz/issues/312#issuecomment-462675101
if [ ${#publicIP} -eq 0 ]; then
localIP=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
echo "WARNING: No publicIP information at all - working with placeholder: ${localIP}" >> $logFile
freshPublicIP="${localIP}"
fi
fi
fi
# set publicip value in raspiblitz.conf
if [ ${#freshPublicIP} -eq 0 ]; then
echo "WARNING: Was not able to determine external IP on startup." >> $logFile
echo "WARNING: Was not able to determine external IP/domain on startup." >> $logFile
else
publicIPValueExists=$( sudo cat ${configFile} | grep -c 'publicIP=' )
if [ ${publicIPValueExists} -gt 1 ]; then
@ -344,10 +371,10 @@ if [ ${configExists} -eq 1 ]; then
fi
if [ ${publicIPValueExists} -eq 0 ]; then
echo "create value (${freshPublicIP})" >> $logFile
echo "publicIP=${freshPublicIP}" >> $configFile
echo "publicIP='${freshPublicIP}'" >> $configFile
else
echo "update value (${freshPublicIP})" >> $logFile
sed -i "s/^publicIP=.*/publicIP=${freshPublicIP}/g" ${configFile}
sed -i "s/^publicIP=.*/publicIP='${freshPublicIP}'/g" ${configFile}
fi
fi

2
home.admin/assets/lnd.service

@ -10,7 +10,7 @@ After=bitcoind.service
[Service]
EnvironmentFile=/mnt/hdd/raspiblitz.conf
ExecStart=/usr/local/bin/lnd --externalip=${publicIP}
ExecStart=/usr/local/bin/lnd --externalip=${publicIP}:{lndPort}
PIDFile=/home/bitcoin/.lnd/lnd.pid
User=bitcoin
Group=bitcoin

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

@ -0,0 +1,231 @@
#!/usr/bin/python3
import sys, subprocess, re
from pathlib import Path
# IDEA: At the momemt its just Reverse-SSh Tunnels thats why [INTERNAL-PORT]<[EXTERNAL-PORT]
# 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
# display config script info
if len(sys.argv) <= 1 or sys.argv[1] == "-h" or sys.argv[1] == "help":
print("forward ports from another server to raspiblitz with reverse SSH tunnel")
print("internet.sshtunnel.py [on|off|restore] [USER]@[SERVER] \"[INTERNAL-PORT]<[EXTERNAL-PORT]\"")
print("note that [INTERNAL-PORT]<[EXTERNAL-PORT] can one or multiple forwardings")
sys.exit(1)
#
# CONSTANTS
# sudo journalctl -f -u autossh-tunnel
#
SERVICENAME="autossh-tunnel.service"
SERVICEFILE="/etc/systemd/system/"+SERVICENAME
SERVICETEMPLATE="""# see config script internet.sshtunnel.py
[Unit]
Description=AutoSSH tunnel service
After=network.target
[Service]
User=root
Group=root
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -N -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" [PLACEHOLDER]
StandardOutput=journal
[Install]
WantedBy=multi-user.target
"""
# get LND port form lnd.conf
LNDPORT = subprocess.getoutput("sudo cat /mnt/hdd/lnd/lnd.conf | grep '^listen=*' | cut -f2 -d':'")
if len(LNDPORT) == 0:
LNDPORT="9735"
#
# RESTORE = SWITCHING ON with restore flag on
# on restore other external scripts dont need calling
#
forwardingLND = False
restoringOnUpdate = False
if sys.argv[1] == "restore":
print("internet.sshtunnel.py -> running with restore flag")
sys.argv[1] = "on"
restoringOnUpdate = True
#
# SWITCHING ON
#
if sys.argv[1] == "on":
# check if already running
isRunning = subprocess.getoutput("sudo systemctl --no-pager | grep -c '%s'" % (SERVICENAME))
if int(isRunning) > 0:
print("SSH TUNNEL ALREADY ACTIVATED - run 'internet.sshtunnel.py off' first to set new tunnel")
sys.exit(1)
# check server address
if len(sys.argv) < 3:
print("[USER]@[SERVER] missing - use 'internet.sshtunnel.py -h' for help")
sys.exit(1)
if sys.argv[2].count("@") != 1:
print("[USER]@[SERVER] wrong - use 'internet.sshtunnel.py -h' for help")
sys.exit(1)
ssh_server = sys.argv[2]
# genenate additional parameter for autossh (forwarding ports)
if len(sys.argv) < 4:
print("[INTERNAL-PORT]<[EXTERNAL-PORT] missing")
sys.exit(1)
ssh_ports=""
additional_parameters=""
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]))
sys.exit(1)
# get ports
sys.argv[i] = re.sub('"','', sys.argv[i] )
ports = sys.argv[i].split("<")
port_internal = ports[0]
port_external = ports[1]
if port_internal.isdigit() == False:
print("[INTERNAL-PORT]<[EXTERNAL-PORT] internal not number '%s'" % (sys.argv[i]))
sys.exit(1)
if port_external.isdigit() == False:
print("[INTERNAL-PORT]<[EXTERNAL-PORT] external not number '%s'" % (sys.argv[i]))
sys.exit(1)
if port_internal == LNDPORT:
forwardingLND = True
if port_internal != port_external:
print("FAIL: When tunneling your local LND port '%s' it needs to be the same on the external server, but is '%s'" % (LNDPORT,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")
sys.exit(1)
ssh_ports = ssh_ports + "\"%s\" " % (sys.argv[i])
additional_parameters= additional_parameters + "-R %s:localhost:%s " % (port_external,port_internal)
i=i+1
# genenate additional parameter for autossh (server)
ssh_ports = ssh_ports.strip()
additional_parameters= additional_parameters + ssh_server
# generate custom service config
service_data = SERVICETEMPLATE.replace("[PLACEHOLDER]", additional_parameters)
# debug print out service
print()
print("*** New systemd service: %s" % (SERVICENAME))
print(service_data)
# write service file
service_file = open("/home/admin/temp.service", "w")
service_file.write(service_data)
service_file.close()
subprocess.call("sudo mv /home/admin/temp.service %s" % (SERVICEFILE), shell=True)
# check if SSH keys for root user need to be created
print()
print("*** Checking root SSH pub keys")
ssh_pubkey=""
try:
ssh_pubkey = subprocess.check_output("sudo cat /root/.ssh/id_rsa.pub", shell=True, universal_newlines=True)
print("OK - root id_rsa.pub file exists")
except subprocess.CalledProcessError as e:
print("Generating root SSH keys ...")
subprocess.call("sudo sh -c 'yes y | sudo -u root ssh-keygen -b 2048 -t rsa -f ~/.ssh/id_rsa -q -N \"\"'", shell=True)
ssh_pubkey = subprocess.check_output("sudo cat /root/.ssh/id_rsa.pub", shell=True, universal_newlines=True)
# 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")
# 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:
file_content = file_content+"\nsshtunnel=''"
file_content = re.sub("sshtunnel=.*", "sshtunnel='%s %s'" % (ssh_server, ssh_ports), file_content)
if restoringOnUpdate == False:
serverdomain=ssh_server.split("@")[1]
# make sure serverdomain is set as tls alias
print("Setting server as tls alias and generating new certs")
subprocess.call("sudo sed -i \"s/^#tlsextradomain=.*/tlsextradomain=/g\" /mnt/hdd/lnd/lnd.conf", shell=True)
subprocess.call("sudo sed -i \"s/^tlsextradomain=.*/tlsextradomain=%s/g\" /mnt/hdd/lnd/lnd.conf" % (serverdomain), shell=True)
subprocess.call("sudo /home/admin/config.scripts/lnd.newtlscert.sh", shell=True)
if forwardingLND:
# setting server explicitly on LND if LND port is forwarded
print("Setting server domain for LND Port")
subprocess.call("sudo /home/admin/config.scripts/lnd.setaddress.sh on %s" % (serverdomain), shell=True)
file_content = "".join([s for s in file_content.splitlines(True) if s.strip("\r\n")]) + "\n"
print(file_content)
with open("/mnt/hdd/raspiblitz.conf", "w") as text_file:
text_file.write(file_content)
print("DONE")
# 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)
# enable service
print()
print("*** Enabling systemd service: %s" % (SERVICENAME))
subprocess.call("sudo systemctl daemon-reload", shell=True)
subprocess.call("sudo systemctl enable %s" % (SERVICENAME), shell=True)
# final info (can be ignored if run by other script)
print()
print("**************************************")
print("*** WIN - SSH TUNNEL SERVICE SETUP ***")
print("**************************************")
print("See chapter 'How to setup port-forwarding with a SSH tunnel?' in:")
print("https://github.com/rootzoll/raspiblitz/blob/master/FAQ.md")
print("- Tunnel service needs final reboot to start.")
print("- After reboot check logs: sudo journalctl -f -u %s" % (SERVICENAME))
print("- Make sure the SSH pub key of this RaspiBlitz is in 'authorized_keys' of %s :" % (ssh_server))
print(ssh_pubkey)
print()
#
# SWITCHING OFF
#
elif sys.argv[1] == "off":
print("*** Disabling systemd service: %s" % (SERVICENAME))
subprocess.call("sudo systemctl stop %s" % (SERVICENAME), shell=True)
subprocess.call("sudo systemctl disable %s" % (SERVICENAME), shell=True)
subprocess.call("sudo rm %s" % (SERVICEFILE), shell=True)
subprocess.call("sudo systemctl daemon-reload", shell=True)
print("OK Done")
print()
print("*** Removing LND Address")
subprocess.call("sudo /home/admin/config.scripts/lnd.setaddress.sh off", shell=True)
print()
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")
#
# UNKOWN PARAMETER
#
else:
print ("unkown parameter - use 'internet.sshtunnel.py -h' for help")

83
home.admin/config.scripts/lnd.setaddress.sh

@ -0,0 +1,83 @@
#!/bin/bash
# INFO : Does not need to be part of update/provision, because
# all data is already on HDD ready
# command info
if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "-help" ]; then
echo "small config script to set a fixed domain or IP for LND"
echo "internet.dyndomain.sh [on|off] [?address]"
exit 1
fi
# 1. parameter [on|off]
mode="$1"
echo "number of args($#)"
# config file
configFile="/mnt/hdd/raspiblitz.conf"
# lnd conf file
lndConfig="/mnt/hdd/lnd/lnd.conf"
# check if config file exists
configExists=$(ls ${configFile} | grep -c '.conf')
if [ ${configExists} -eq 0 ]; then
echo "FAIL - missing ${configFile}"
exit 1
fi
# FIXED DOMAIN/IP
if [ "${mode}" = "on" ]; then
address=$2
if [ ${#address} -eq 0 ]; then
echo "missing parameter"
exit 1
fi
echo "switching fixed LND Domain ON"
echo "address(${address})"
# setting value in raspi blitz config
sudo sed -i "s/^lndAddress=.*/lndAddress='${address}'/g" /mnt/hdd/raspiblitz.conf
echo "changing lnd.conf"
# lnd.conf: uncomment tlsextradomain (just if it is still uncommented)
sudo sed -i "s/^#tlsextradomain=.*/tlsextradomain=/g" /mnt/hdd/lnd/lnd.conf
# lnd.conf: domain value
sudo sed -i "s/^tlsextradomain=.*/tlsextradomain=${address}/g" /mnt/hdd/lnd/lnd.conf
# refresh TLS cert
sudo /home/admin/config.scripts/lnd.newtlscert.sh
echo "fixedAddress is now ON"
fi
# switch off
if [ "${mode}" = "off" ]; then
echo "switching fixedAddress OFF"
# stop services
echo "making sure services are not running"
sudo systemctl stop lnd 2>/dev/null
# setting value in raspi blitz config
sudo sed -i "s/^lndAddress=.*/lndAddress=/g" /mnt/hdd/raspiblitz.conf
echo "changing lnd.conf"
# lnd.conf: comment tlsextradomain out
sudo sed -i "s/^tlsextradomain=.*/#tlsextradomain=/g" /mnt/hdd/lnd/lnd.conf
# refresh TLS cert
sudo /home/admin/config.scripts/lnd.newtlscert.sh
echo "fixedAddress is now OFF"
fi
echo "may needs reboot to run normal again"
exit 0

2
home.admin/config.scripts/lnd.setname.sh

@ -17,7 +17,7 @@ if [ ${#newName} -eq 0 ]; then
dialog --backtitle "Set LND Name/Alias" --inputbox "ENTER the new Name/Alias for LND node:
(free to choose, one word, use basic characters)
" 8 52 2>./.tmp
newName=$( cat ./.tmp )
newName=$( cat ./.tmp | tr -dc '[:alnum:]\n\r' )
if [ ${#newName} -eq 0 ]; then
echo "FAIL input cannot be empty"
exit 1

13
home.admin/config.scripts/lnd.setport.sh

@ -1,6 +1,7 @@
#!/bin/bash
# based on: https://github.com/rootzoll/raspiblitz/issues/100#issuecomment-465997126
# based on: https://github.com/rootzoll/raspiblitz/issues/386
if [ $# -eq 0 ]; then
echo "small config script set the port LND is running on"
@ -62,9 +63,19 @@ sudo systemctl disable lnd
echo "change port in lnd config"
sudo sed -i "s/^listen=.*/listen=0.0.0.0:${portnumber}/g" /mnt/hdd/lnd/lnd.conf
# add to raspiblitz.config (so it can survive update)
valueExists=$(sudo cat /mnt/hdd/raspiblitz.conf | grep -c 'lndPort=')
if [ ${valueExists} -eq 0 ]; then
# add as new value
echo "lndPort=${portnumber}" >> /mnt/hdd/raspiblitz.conf
else
# update existing value
sudo sed -i "s/^lndPort=.*/lndPort=${portnumber}/g" /mnt/hdd/raspiblitz.conf
fi
# editing service file
echo "editing /etc/systemd/system/lnd.service"
sudo sed -i "s/^ExecStart=\/usr\/local\/bin\/lnd.*/ExecStart=\/usr\/local\/bin\/lnd --externalip=\${publicIP}:${portnumber}/g" /etc/systemd/system/lnd.service
sudo sed -i "s/^ExecStart=\/usr\/local\/bin\/lnd.*/ExecStart=\/usr\/local\/bin\/lnd --externalip=\${publicIP}:\${lndPort}/g" /etc/systemd/system/lnd.service
# enable service again
echo "enable service again"

Loading…
Cancel
Save