In my previous post I described a method for a boot-activated remote-admin option for my parents’ computer.
On 2nd thought, it is not always a good idea to rely on changing system-wide configurations (such as sshd_config, firewall…)
In this post I’ll basically re-do the whole thing. This time an extra SSH-server is started, in addition to any existing ones, listening on a custom port + custom config options. The firewall is dealt with in the script as well.
For sake of completeness, I will repeat all steps of the previous post and expand where necessary.
I wanted and needed something simple, something that could be activated in the bootloader menu (grub 2), something that didn’t leave the machine wide-open when absolutely not needed, something that would be robust and wasn’t necessarily depending on a working GUI.
1) KERNEL BOOT PARAMETERS
The boot-parameters that were used for the currently running kernel can be found in the file ‘/proc/cmdline’, easy to read and evaluate.
2) GRUB2 CONFIGURATION
The idea is to create a custom boot-menu entry for the Linux machine and adding a keyword of choice as a boot-parameter.
On openSUSE one can add custom grub2 stuff to /etc/grub.d/, e.g. in a file named ’50_rescue_ssh’. The idea is to use an existing menu-entry from the grub2 config file (see /boot/grub2/grub.cfg) as a template.
On 13.2, you’ll find an entry similar to the following in ‘/boot/grub2/grub.cfg’:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
menuentry 'openSUSE 13.2' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' XXXXXX-XXXX-XXXX... else search --no-floppy --fs-uuid --set=root XXXXXX-XXXX-XXXX... fi echo 'Loading Linux 3.16.7-24-desktop ...' linux /vmlinuz-3.16.7-24-desktop root=UUID=YYYYYY-YYYY-YYYY... resume=/dev/disk/by-id/ata-ZZZZZZZZ-part5 splash=silent quiet showopts echo 'Loading initial ramdisk ...' initrd /initrd-3.16.7-24-desktop } |
Copy this section to ‘/etc/grub.d/50_rescue_ssh’, and make it look something like the following. Note, the new name, added kernel parameter, modified initrd/vmlinuz lines, removed ‘resume’. The version-less links to initrd/vmlinuz should always be present and link to the current kernel used. Make sure the file permissions and ownership are the same as all the other files in that folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#!/bin/sh exec tail -n +3 $0 # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. # THIS IS JUST A DEMO! USE YOUR OWN (see /boot/grub2/grub.conf) # make sure to use 'vmlinuz' and 'initrd' WITHOUT kernel version numbers as below # don't forget to add the kernel paramter 'start_rescue_ssh' # # Run 'grub2-mkconfig > /boot/grub2/grub.cfg' or 'yast2 bootloader' after changes to '/etc/grub.d/'. # menuentry 'Rescue SSH' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' XXXXXX-XXXX-XXXX... else search --no-floppy --fs-uuid --set=root XXXXXX-XXXX-XXXX... fi echo 'Loading Linux ...' linux /vmlinuz root=UUID=YYYYYY-YYYY-YYYY... splash=silent quiet showopts start_rescue_ssh echo 'Loading initial ramdisk ...' initrd /initrd } |
Once that is done, run ‘grub2-mkconfig > /boot/grub2/grub.cfg’ to update grub2. If you reboot now, there should be an additional boot option named ‘Rescue SSH’ in grub2’s boot menu, which should start up normally (but without resume).
With this modified menu entry running, the parameter ‘start_rescue_ssh’ will show up in ‘/proc/cmdline’, ready for further evaluation.
3) PASSWORD-LESS SSH LOGIN + PORT FORWARDING / FIREWALL
To make use of the SSH-server, we need to activate port-forwarding in the router that connects to the ISP. Please refer to the manual of said device. Usually it is quite easy to do. The standard SSH-port is 22, which is occupied by the standard SSH-server. Choose something else, maybe 66.
Adapting the firewall to allow incoming traffic is handled by a script, which we will take a look at further down.
To prepare for password-less logins using a public key, the remote user must transfer his public key (e.g. ‘id_rsa.pub’) to the local account to be logged into.
The remote user ‘son’ wanting to log in to the local account ‘dad’ must append his public key ‘son@gamer:/home/son/.ssh/id_rsa.pub’ to ‘dad@mozart:/home/dad/.ssh/authorized_keys’.
This can be done in two ways. Either manually copy/append the contents of ‘id_rsa.pub’ (sun@gamer) to ‘authorized_keys’ (dad@mozart), or use the tool ‘ssh-copy-id’. For the latter option, the standard SSH-server on @mozart must be up and running (port 22).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
as son@gamer: ============= ssh-copy-id -i /home/son/.ssh/id_rsa.pub -p 22 dad@mozart output: ======= /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys Password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'dad@mozart'" and check to make sure that only the key(s) you wanted were added. |
Password-less login to ‘dad@mozart’ should work now.
An additional SSH-server will be started by a script after booting. It will make sure the SSH-server is configured in such a way that it only allows public-key authentication for normal users. Root login will be rejected.
4) EMAIL CONFIGURATION – works with YAHOO and another provider
To make sure that dad’s machine @mozart can send out emails using his usual email account, some modifications to ‘/home/dad/.mailrc’ are necessary.
1 2 3 4 5 6 7 8 |
set asksub append dot save crt=20 ignore Received Message-Id Resent-Message-Id Status Mail-From Return-Path Via set smtp=smtp.provider.com:25 set smtp-use-starttls set smtp-auth=login set smtp-auth-password=whatever set smtp-auth-user=dad@provider.com |
You can test outgoing emails by issuing the following command (run as dad@mozart):
1 |
echo "email body" | mail -v -r dad@provider.com -s subject son@somewhereelse.com |
This should send out an email + show the connection details going back and forth. It is crucial that this step works. If it doesn’t work, make sure that ‘.mailrc’ has correct ownership and permissions: dad.users 600 (rw——-).
5) EVALUATION OF BOOT PARAMETERS
On openSUSE, you can add custom stuff to a script ‘/etc/init.d/after.local’ which is run after a runlevel has been reached.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#! /bin/sh # # Copyright (c) 2010 SuSE LINUX Products GmbH, Germany. All rights reserved. # # Author: Werner Fink, 2010 # # /etc/init.d/after.local # # script with local commands to be executed from init after all scripts # of a runlevel have been executed. # # Here you should add things, that should happen directly after # runlevel has been reached. # USER="dad"; SSH_PORT="66"; SSHD_BIN=`which sshd`; CMD_LINE=/proc/cmdline; LOOK_FOR="start_rescue_ssh"; RESULT=`grep $LOOK_FOR $CMD_LINE`; EMAIL_FROM="dad@provider.com"; EMAIL_TO="son@somewhereelse.com"; EMAIL_SUBJECT="Fix dad's computer..."; EMAIL_TEXT="Fix dad's computer...\n\nShared: ssh -4 -p SSH_PORT -t -L 6900:localhost:5900 USER@REMOTE_IP 'x11vnc -ncache -localhost -display :0'\n\nStand-alone: ssh -4 -p SSH_PORT -t -L 6900:localhost:5900 USER@REMOTE_IP 'x11vnc -create -ncache -localhost'\n\nvncviewer -compresslevel 9 -quality 5 -encodings tight localhost:6900"; if [[ -n $RESULT ]]; then # make sure WiFi is really up # make sure WiFi is set to 'system' connection in NetworkManager, so it starts without user login sleep 60; echo "booted with 'start_rescue_ssh': starting ssh"; logger "booted with 'start_rescue_ssh': starting sshd"; # punch a hole into the firewall iptables -I INPUT 1 -p tcp --dport $SSH_PORT -j ACCEPT # start extra SSH server $SSHD_BIN -4 -p $SSH_PORT -o "PermitRootLogin no" -o "PubkeyAuthentication yes" -o "PasswordAuthentication no" -o "ChallengeResponseAuthentication no" IP_FILE=`sudo -u $USER mktemp`; sudo -u $USER sh -c "curl -s checkip.dyndns.org > $IP_FILE"; REMOTE_IP=$(cat $IP_FILE | sed 's/^<.*Current\ IP\ Address:\ //' | sed 's/\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/'); rm $IP_FILE; EMAIL_TEXT=$(echo $EMAIL_TEXT | sed "s/REMOTE_IP/$REMOTE_IP/g" | sed "s/USER/$USER/g" | sed "s/SSH_PORT/$SSH_PORT/g"); sudo -u $USER sh -c "echo -e \"$EMAIL_TEXT\" | mail -s \"$EMAIL_SUBJECT\" -r \"$EMAIL_FROM\" \"$EMAIL_TO\""; fi |
This script checks for the custom boot parameter ‘start_rescue_ssh’, if that is found it starts an additional SSH-server (in this case listening on port 66), configured to only allow public-key logins for non-root users, and sends an email from ‘dad@provider.com’ to ‘son@somewhereelse.com’ containing information about dad’s current external IP address (router with enabled port-forwarding) and how to connect.
A ‘hole’ is punched into the firewall by inserting an appropriate rule at the beginning of the INPUT chain, which should be compatible with running firewalls. Appending that rule at the end might not work, if the last entry of the chain is equivalent to ‘deny all’ or ‘drop all’.
If the email gets through, it should look this this:
1 2 3 4 5 6 7 |
Fix dad's computer... Shared: ssh -4 -p 66 -t -L 6900:localhost:5900 dad@AAA.BBB.CCC.DDD 'x11vnc -ncache -localhost -display :0' Stand-alone: ssh -4 -p 66 -t -L 6900:localhost:5900 dad@AAA.BBB.CCC.DDD 'x11vnc -create -ncache -localhost' vncviewer -compresslevel 9 -quality 5 -encodings tight localhost:6900 |
The ‘shared’ option allows for shared desktop experience, when ‘dad’ is logged in.
The ‘stand-alone’ option works if dad is not logged in or no X server is running.
Once the ssh connection is up, run the ‘vncviewer’ line for a graphical user interface. If you just need a console login, connect with ssh as usual (skip -t -L … ‘x11vnc…’).
If WiFi + networkmanager is used, you may have to set the WiFi-connection to ‘system’, to make sure it is up and running, even if no user is logged in!
Use with extreme caution, test test test !
Download here.