SSH summerschool jump hosts en file transferring hero image
CLOUD & MANAGED SERVICESCLOUDSSH
10/10/2018 • Jan Beerden

SSH Summer School: jump hosts en bestandsoverdracht

Deze blog post is het laatste deel van een 3-delige serie over SSH (Secure Shell) verbindingen met OpenSSH. In dit laatste deel van de serie ga ik het hebben over jump/bastion hosts, het gebruik van 'screen' en het overzetten van bestanden. Het doel van deze blog post serie is om je meer te leren over SSH. In deze blog posts ga ik ervan uit dat je een UNIX-achtig besturingssysteem gebruikt met OpenSSH.

Laten we beginnen met te praten over spring/bastion hosts en waarom ze zo handig zijn. Het komt steeds vaker voor dat de server op afstand die je wilt benaderen niet rechtstreeks bereikbaar is. In plaats daarvan moet je door een 'sprong': een jump of bastion host. En dat is een goede zaak, want:

  • meestal mogen applicatieservers niet rechtstreeks aan het internet worden blootgesteld.
  • als je IPv4 gebruikt, is er geen noodzaak voor een publiek IPv4-adres voor elk van je servers.
  • dan hoeft de firewall van slechts één host geconfigureerd te worden om de IP van je kantoor toe te laten, wat veel werk bespaart wanneer de IP verandert.

Het passeren van een jump host kan vervelend zijn omdat je door meerdere servers moet SSH-en. Gelukkig zijn er meerdere manieren om dit te doen. Ik heb hieronder 4 methodes opgesomd!

Hoe geraak ik door een jump host?

1. 'Manueel'

Eén methode om door een jump host te gaan is door te SSH-en naar de jump host en dan vanaf de jump host SSH-en naar je server.

user@local-computer $ ssh jumphostuser@my-jump-host
jumphostuser@my-jump-host $ ssh remoteserveruser@my-remote-server
[remoteserveruser@my-remote-server ~]$

SSH key

Je zult snel tot de conclusie komen dat verbinding maken met je server op afstand vanaf de jump host een SSH sleutel vereist op de jump host. Een oplossing zou kunnen zijn om een SSH sleutel aan te maken op de jump host, maar dit is geen optie voor jump hosts die regelmatig vervangen worden. Dit is waarschijnlijk geen geschikte methode voor de meesten van ons, dus laten we verder gaan met de volgende methode. Oh, en tussen haakjes: kopieer nooit je lokale SSH sleutel naar een andere host, zoals een jump host!

2. Agent forwarding

Ik heb het ssh-agent concept al uitgelegd in de eerste blog post van deze serie. Met agent forwarding kun je je lokale ssh-agent op een remote server zetten, zoals een jump host. Je kunt de opdrachtregeloptie -A gebruiken of de optie ForwardAgent in het configuratiebestand.

user@local-computer $ ssh-add
Enter passphrase for /Users/janbeerden/.ssh/id_rsa:
Identity added: /Users/user/.ssh/id_rsa (/Users/user/.ssh/id_rsa)
 
user@local-computer $ ssh -A jumphostuser@my-jump-host
jumphostuser@my-jump-host $ ssh remoteserveruser@my-remote-server
[remoteserveruser@my-remote-server ~]$

Door dit te doen, hebt je niet langer een intermediaire sleutel nodig. Je account op de jump host en de remote server zouden alleen het publieke gedeelte van je lokale SSH sleutel moeten bevatten. Makkelijk genoeg, toch? (smile)

Maar omdat je je lokale ssh-agent blootstelt aan de jump host, kan de jump host je SSH-sleutel gebruiken zonder de passphrase nodig te hebben. Als je de enige bent die deze jump host gebruikt (en onderhoudt), zit je waarschijnlijk goed. Als dat niet het geval is (waarschijnlijk meestal), zou iemand je sleutel kunnen gebruiken terwijl die naar de jump host wordt doorgestuurd.

Bij het starten van een SSH-verbinding met agent forwarding ingeschakeld, zal de SSH-server een socket aanmaken om je SSH-agent bloot te stellen. Alleen je gebruiker op de jump host zal autorisaties hebben op deze socket, maar deze beperkingen zijn niet van toepassing op de root gebruiker of een andere gebruiker die voldoende permissies heeft via sudo.

3. ProxyCommand

Met de optie ProxyCommand kunt je een commando opgeven dat moet worden gebruikt om verbinding te maken met de server op afstand. Deze optie kan worden gebruikt om SSH-verbindingen te 'ketenen'. Door "ssh -W" als ProxyCommand te gebruiken, vragen we dat standaard input en output op de client wordt doorgestuurd naar Hostname over het beveiligde kanaal naar mijn-jump-host.

Host my-jump-host
  Hostname 192.168.0.10
  User jumphostuser
 
Host my-remote-server
  Hostname 192.168.5.10
  User remoteserveruser
  ProxyCommand ssh my-jump-host -W %h:%p

Zoals je ziet, vereist dit enige configuratie, maar dat hoeft maar één keer te gebeuren.

user@local-computer $ ssh my-remote-server
[remoteserveruser@my-remote-server ~]$

Zodra deze configuratie in orde is, kunt je 'rechtstreeks' ssh-en op je server op afstand. Het passeren van de bastion host wordt verzorgd door het ProxyCommand.

4. ProxyJump (deze raad ik zeker aan!)

Sinds OpenSSH 7.3 is er een eenvoudiger te configureren alternatief voor ProxyCommand, ProxyJump genaamd.

Host my-jump-host
  Hostname 192.168.0.10
  User jumphostuser
 
Host my-remote-server
  Hostname 192.168.5.10
  User remoteserveruser
  ProxyJump my-jump-host

Zoals je kunt zien, is de configuratie van deze optie een stuk eenvoudiger.

user@local-computer $ ssh my-remote-server
[remoteserveruser@my-remote-server ~]$

Verbinding maken met je server op afstand is niet anders dan de ProxyCommand methode. Als je verbinding wil maken met een remote server zonder deze toe te voegen aan je configuratiebestand via een jump host (die je hebt toegevoegd aan je config file), is ProxyJump ook heel eenvoudig.

user@local-computer $ ssh remoteserveruser@192.168.0.20 -J my-jump-host

Wanneer je een SSH configuratiebestand deelt met je team, kan je ook de hierboven getoonde configuratie toevoegen. Zij zullen het zeker op prijs stellen dat zij de configuratie niet zelf hoeven te maken of toe te voegen! Zorg ervoor dat je de conventies volgt die vermeld staan in deel 1 van deze reeks.

Ik raad deze methode aan in plaats van de andere, omdat:

  • methode 1 is te veel moeite elke keer dat je wilt SSH-en naar je server op afstand,
  • methode 2 is een veiligheidsrisico en vereist nog steeds meerdere stappen elke keer dat je wilt SSH-en naar je server op afstand,
  • de syntax van methode 3 is complexer en dus minder gemakkelijk te onthouden dan die van de ProxyJump-methode.

Methode 3 en 4 geven je ook het voordeel dat je bestanden direct naar je server op afstand kunt overbrengen met scp of sftp zonder ze eerst naar de jump host te hoeven kopiëren. Maar hoe begin je dan precies met het overzetten van bestanden? We zullen in de details van bestandsoverdracht duiken, maar laat me je eerst vertellen over het gebruik van 'screen'.

Gebruik 'Screen'

computer screen

Aangezien elke jump host een extra 'point of failure' introduceert, is dit het perfecte moment om 'Screen' te gaan gebruiken. Is je SSH-sessie ooit verbroken terwijl je een lang en/of delicaat proces uitvoerde op een server op afstand? Wanneer je SSH sessie wordt verbroken, zullen alle processen die gestart zijn in de sessie en die op de voorgrond draaien worden beëindigd. Hierdoor moet je helemaal opnieuw beginnen of, afhankelijk van het proces, een puinhoop achterlaten die je handmatig moet opruimen. Gelukkig kunt je voorkomen dat dit een probleem wordt door 'screen' te gebruiken. Van de man pagina:

Screen is een schermvullende window manager die een fysieke terminal kan multiplexen tussen verschillende processen (typisch interactieve shells).

Enkele voordelen van het gebruik van het scherm:

  • je shell blijft actief wanneer je SSH-sessie wordt verbroken,
  • je kunt lange processen uitvoeren op een server op afstand zonder dat je een actieve SSH-verbinding hoeft te onderhouden,
  • je kunt meerdere vensters van een enkele SSH-sessie gebruiken.

Eerst en vooral moet Screen geïnstalleerd zijn op je server op afstand. Als Screen nog niet geïnstalleerd is, kun je de pakketbeheerder van je systeem gebruiken om het te installeren.

Een nieuw scherm starten

Een scherm starten is heel eenvoudig:

[remoteserveruser@my-remote-server ~]$ screen

Het scherm zal een nieuwe shell aanmaken, net zoals SSH'en op een server zou doen.

Loskoppelen van een scherm

Het verschil met een 'standaard' shell is dat je de verbinding kunt verbreken, zonder alle sub-processen te onderbreken. Eerst moet je het escape commando ingeven, dat is CTRL+a, gevolgd door CTRL+d.

[detached from 4389.pts-0.my-remote-server]
[remoteserveruser@my-remote-server ~]$

Screen zal je vertellen dat het je heeft losgekoppeld van een scherm sessie. In dit geval heet de sessie 4389.pts-0.my-remote-server. Als je de shell wilt verlaten in plaats van de verbinding te verbreken voor de schermsessie, kunt je dat doen alsof het een andere shell is. Enter:

  • exit
  • CTRL+d

(warning) Wees echter wel voorzichtig! Screen beschermt je niet tegen het per ongeluk verlaten van je shell. (warning)

Lijst van actieve scherm sessies

Met de -ls optie kun je een lijst maken van alle actieve scherm sessies.

[remoteserveruser@my-remote-server ~]$ screen -ls
There are screens on:
    4405.pts-0.my-remote-server (Detached)
    4389.pts-0.my-remote-server (Detached)
2 Sockets in /var/run/screen/S-remoteserveruser.

Elke regel bestaat uit het proces-id en de sessienaam, gescheiden door een punt.

Een nieuw scherm starten met een aangepaste sessienaam

Zoals je kunt zien in de output hierboven, kunnen schermsessies moeilijk te identificeren zijn. Daarom kan het verstandig zijn om je schermsessie een naam te geven wanneer je deze opstart:

[remoteserveruser@my-remote-server ~]$ screen -S server-upgrade
[remoteserveruser@my-remote-server ~]$ screen -ls
There are screens on:
        4475.server-upgrade     (Attached)
1 Socket in /var/run/screen/S-remoteserveruser.

Koppelen aan een losgekoppelde schermsessie

Als je opnieuw wilt koppelen aan een schermsessie, kunt je dat doen met de -r optie. Deze optie neemt ofwel het proces id of de sessienaam als parameter.

[remoteserveruser@my-remote-server ~]$ screen -r server-upgrade

Meerdere vensters in één schermsessie

In elk van de volgende subparagrafen wordt ervan uitgegaan dat je aan een schermsessie bent gekoppeld.

Een nieuw venster maken binnen je schermsessie

Door CTRL+a gevolgd door CTRL+c te gebruiken, creëer je een nieuw venster.

Lijst van geopende vensters

Door CTRL+a gevolgd door CTRL+w te gebruiken, krijgt je een lijst van geopende vensters.

[remoteserveruser@my-remote-server ~]$
 
 
0$ bash  1-$ bash  2*$ bash

Zoals je kan zien in de uitvoer hierboven, heb ik 3 open vensters, geïdentificeerd door een nummer gevolgd door de titel.

Schakelen tussen vensters

Er zijn 4 (5) manieren om tussen vensters te schakelen:

  1. overschakelen naar een specifiek venster:
    • CTRL+a gevolgd door het nummer van het venster
    • CTRL+a gevolgd door "; deze methode is waarschijnlijk de gemakkelijkste omdat het je een interactieve vensterkiezer toont. Met de pijltjestoetsen kun je het gewenste scherm selecteren en op de Enter-toets drukken om het te selecteren.
  2. overschakelen naar het volgende venster: CTRL+a gevolgd door n
  3. overschakelen naar het vorige venster: CTRL+a gevolgd door p
  4. overschakelen naar het laatste venster: CTRL+a gevolgd door o

Andere schermtoetsenbindingen

Er zijn verschillende toetsenbindingen die kunnen worden gebruikt in een schermsessie, na het geven van het besturingscommando (CTRL+a). Je kunt een overzicht krijgen van de beschikbare toetsenbindingen door op de ? toets te drukken. Druk eerst op CTRL+a, en dan op de ? toets.

                     Screen key bindings, page 1 of 2.
 
                     Command key:  ^A   Literal ^A:  a
 
break       ^B b         license     ,            removebuf   =
clear       C            lockscreen  ^X x         reset       Z
colon       :            log         H            screen      ^C c
copy        ^[ [         login       L            select      '
detach      ^D d         meta        a            silence     _
digraph     ^V           monitor     M            split       S
displays    *            next        ^@ ^N sp n   suspend     ^Z z
dumptermcap .            number      N            time        ^T t
fit         F            only        Q            title       A
flow        ^F f         other       ^A           vbell       ^G
focus       ^I           pow_break   B            version     v
hardcopy    h            pow_detach  D            width       W
help        ?            prev        ^H ^P p ^?   windows     ^W w
history     { }          quit        \            wrap        ^R r
info        i            readbuf     <            writebuf    >
kill        K k          redisplay   ^L l         xoff        ^S s
lastmsg     ^M m         remove      X            xon         ^Q q
 
 
                [Press Space for next page; Return to end.]

Een van mijn favorieten is kopiëren. Zoals de naam al doet vermoeden, kan het worden gebruikt om tekst van het ene venster naar het andere te kopiëren. Voor een volledig overzicht en uitleg van de beschikbare commandoregelopties en toetsenbindingen, zie de man pagina.

Overzetten van bestanden

Zoals hierboven beloofd, zullen we het hebben over het overzetten van bestanden. Er zijn een aantal methoden om bestanden over te brengen naar, van en tussen hosts op afstand. In dit gedeelte ga ik het hebben over bestandsoverdracht via SCP, SFTP en SSH 'streaming'. Alle drie deze methoden werken ook bij gebruik van een jump host als je de ProxyCommand of ProxyJump directief gebruikt zoals hierboven beschreven.

SCP

scp of secure copy maakt het mogelijk om bestanden veilig te kopiëren van, naar of tussen hosts op afstand.

Van

user@local-computer $ scp my-remote-server:~/file.txt ~/Downloads/local/

Naar

user@local-computer $ tar -zcf - /var/log/ | ssh remoteserveruser@my-remote-server "cat - > ~/log-archive.tgz"

Tussen

user@local-computer $ scp my-remote-server:~/file.txt my-other-remote-server:~/

Voor meer informatie over het gebruik van scp, kijk op de man pagina.

user@local-computer $ man scp

SFTP

sftp of secure file transfer protocol is een interactief programma voor bestandsoverdracht, vergelijkbaar met ftp, waarmee je veilig bestanden kunt kopiëren naar of van een server op afstand. Door het commando "?" in te voeren, krijgt je een lijst met mogelijke commando's.

user@local-computer $ sftp my-remote-server
sftp> ?
Available commands:
bye                                Quit sftp
cd path                            Change remote directory to 'path'
chgrp grp path                     Change group of file 'path' to 'grp'
chmod mode path                    Change permissions of file 'path' to 'mode'
chown own path                     Change owner of file 'path' to 'own'
df [-hi] [path]                    Display statistics for current directory or
                                   filesystem containing 'path'
exit                               Quit sftp
get [-afPpRr] remote [local]       Download file
reget [-fPpRr] remote [local]      Resume download file
reput [-fPpRr] [local] remote      Resume upload file
help                               Display this help text
lcd path                           Change local directory to 'path'
lls [ls-options [path]]            Display local directory listing
lmkdir path                        Create local directory
ln [-s] oldpath newpath            Link remote file (-s for symlink)
lpwd                               Print local working directory
ls [-1afhlnrSt] [path]             Display remote directory listing
lumask umask                       Set local umask to 'umask'
mkdir path                         Create remote directory
progress                           Toggle display of progress meter
put [-afPpRr] local [remote]       Upload file
pwd                                Display remote working directory
quit                               Quit sftp
rename oldpath newpath             Rename remote file
rm path                            Delete remote file
rmdir path                         Remove remote directory
symlink oldpath newpath            Symlink remote file
version                            Show SFTP version
!command                           Execute 'command' in local shell
!                                  Escape to local shell
?                                  Synonym for help

Voor meer informatie over het gebruik van sftp, zie de man pagina.

user@local-computer $ man sftp

'Stream' via SSH

Stel dat je een archief nodig hebt van de logbestanden op je externe server, maar je hebt niet genoeg ruimte op die server om het archief te maken. In plaats van het archief op de externe server aan te maken en het dan te kopiëren, zou je het ook naar je lokale machine kunnen 'streamen'. Net als scp kan deze methode worden gebruikt om bestanden te kopiëren van, naar of tussen servers op afstand.

Van

user@local-computer $ ssh remoteserveruser@my-remote-server "tar -zcf - /var/log/" > ~/log-archive.tgz

Naar

user@local-computer $ tar -zcf - /var/log/ | ssh remoteserveruser@my-remote-server "cat - > ~/log-archive.tgz"

Tussen

user@local-computer $ ssh remoteserveruser@my-remote-server "tar -zcf - /var/log/" | ssh remoteserveruser@my-remote-server "cat - > ~/log-archive.tgz"

In de bovenstaande voorbeelden zul je merken dat ik een streepje "-" gebruik als de bestandsnaam, dit is de manier om tar, cat en verschillende andere programma's de opdracht te geven om te schrijven naar standaard output (stdout) of te lezen van standaard input (stdin).

En dat is het dan! Ik weet dat dit nogal lange post is, maar ik wilde hem niet opsplitsen in delen die te klein zouden zijn om op zichzelf interessant te zijn. Bij vragen of opmerkingen, aarzel niet om contact met ons op te nemen!