Sichern der Kommunikation in einer dreistufigen Rails-Anwendung mithilfe von SSH-Tunneln

Einführung

Webanwendungen werden häufig mit drei unterschiedlichen Ebenen erstellt:

  • Die erste Schicht ist die Präsentationsschicht, die der Benutzer sieht.

  • Als Nächstes folgt die Anwendungsebene, die die business logic der Anwendung bereitstellt.

  • Schließlich speichert der Datenlayer die von der Anwendung benötigten Daten.

In einer Ruby on Rails -Anwendung wird dies lose einem Webserver für die Präsentationsschicht, einem Rails-Server für die Anwendungsschicht und einer Datenbank für die Datenschicht zugeordnet. In dieser Konfiguration kommuniziert die Anwendungsschicht mit der Datenschicht, um Daten für die Anwendung abzurufen, die dann dem Benutzer über die Präsentationsschicht angezeigt werden.

Während es möglich ist, alle diese Anwendungen auf einem einzelnen Server zu installieren, erleichtert es das Platzieren jeder Ebene auf einem eigenen Server, die Anwendung zu skalieren. Wenn der Rails-Server beispielsweise zu einem Engpass wird, können Sie weitere Anwendungsserver hinzufügen, ohne die beiden anderen Ebenen zu beeinträchtigen.

In diesem Lernprogramm stellen Sie eine Rails-App in einer dreistufigen Konfiguration bereit, indem Sie eine eindeutige Reihe von Software auf drei separaten Servern installieren, die einzelnen Server und ihre Komponenten für die Kommunikation und Funktion zusammen konfigurieren und die Verbindungen zwischen ihnen mit SSH-Tunneln sichern. Für den Software-Stack verwenden Sie Nginx als Webserver auf der Präsentationsebene und Puma als Rails-Anwendungsserver auf der Anwendungsebene und PostgreSQL als Datenbank auf der Datenschicht.

Voraussetzungen

Um dieses Tutorial abzuschließen, müssen Sie drei Ubuntu 16.04-Server hochfahren. Nennen Sie diese * Web-Server *, * App-Server * und * Datenbank-Server *, und für jeden sollte Private Networking aktiviert sein.

Jeder der drei Server sollte einen Nicht-Root-Benutzer mit "+ sudo " - Berechtigungen sowie eine Firewall haben, die so konfiguriert ist, dass SSH-Verbindungen zugelassen werden (diese können Sie unter https://www.digitalocean.com/community/tutorials/initial konfigurieren -server-setup-with-ubuntu-16-04 [Handbuch zur Ersteinrichtung des Servers]). Im Rahmen dieses Tutorials wird der Benutzer " sudo +" auf jedem Server als "* sammy *" bezeichnet.

Darüber hinaus hat jeder der drei Server seine eigenen Konfigurationsanforderungen:

  • Auf dem * Web-Server *:

  • Installieren und konfigurieren Sie den Nginx-Webserver. Folgen Sie dazu unserem Tutorial unter Installation von Nginx unter Ubuntu 16.04.

  • Auf dem * App-Server *:

  • Installieren Sie Node.js mit der offiziellen PPA, wie unter https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-16-04#how-to-install- beschrieben. using-a-ppa [Installieren von Node.js unter Ubuntu 16.04]. Einige Rails-Funktionen, z. B. die Asset-Pipeline, hängen von einer JavaScript-Laufzeit ab, und Node.js bietet diese Funktionalität.

  • Installieren Sie das Ruby on Rails-Framework. Folgen Sie dazu unserer Anleitung unter How to Install Ruby on Rails mit rbenv unter Ubuntu 16.04. Achten Sie beim Befolgen dieses Tutorials darauf, die neueste Version von Ruby zu installieren, die zum Zeitpunkt des Schreibens Ruby 2.5.1 ist.

  • Installieren Sie PostgreSQL, wie im ersten Abschnitt unseres Tutorials https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-ruby-on-rails-application-on-ubuntu- gezeigt. 14-04 # install-postgresql [So verwenden Sie PostgreSQL mit Ihrer Ruby on Rails-Anwendung unter Ubuntu 14.04]. In diesem Abschnitt wird auch die Installation von + libpq-dev + beschrieben, einem weiteren Paket, das für dieses dreistufige Setup erforderlich ist.

  • Stellen Sie eine Rails-App mit Puma bereit. Wenn Sie keine eigene App zum Bereitstellen haben, folgen Sie unserem Leitfaden unter https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and- nginx-on-ubuntu-14-04 [Bereitstellen einer Rails-App mit Puma und Nginx] zum Bereitstellen einer Beispiel-App. Beachten Sie, dass Sie im Abschnitt "Install rbenv-vars Plugin" dieser Voraussetzung den Datenbankbenutzer und das Kennwort festlegen müssen, um die Werte wiederzugeben, die Sie bei der Installation von PostgreSQL auf dem * Datenbankserver * verwenden. Außerdem müssen Sie den Anschluss "+ 3000 +" durch Ihre Firewall zulassen, damit der Abschnitt "Produktionsdatenbank erstellen" funktioniert. Schließlich müssen Sie die letzten beiden Schritte dieses vorausgesetzten Lernprogramms, "Puma-Upstart-Skript erstellen" und "Nginx installieren und konfigurieren", nicht ausführen.

  • Auf dem * Datenbank-Server *:

  • Installieren und konfigurieren Sie die PostgreSQL-Datenbanksoftware. Folgen Sie unserer Anleitung unter Installation und Verwendung von PostgreSQL unter Ubuntu 16.04, um Anweisungen zu erhalten wie das geht. Wenn Sie dieses Lernprogramm befolgen, erstellen Sie eine PostgreSQL-Rolle für Ihre Rails-App mit den Berechtigungen "+ superuser +" sowie eine Datenbank mit dem gleichen Namen wie die PostgreSQL-Rolle. In diesem Tutorial werden sowohl die PostgreSQL-Rolle als auch die Datenbank als * sammy * bezeichnet.

  • Legen Sie ein Kennwort für die neu erstellte PostgreSQL-Rolle fest. Überspringen Sie den ersten Befehl in „https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04#create -production-database-user [Create Production Database User] “im Puma-Tutorial (mit dem Sie auch den * app-server * eingerichtet haben) und befolgen Sie die restlichen Befehle in diesem Abschnitt, um das Kennwort des Datenbankbenutzers zu ändern . Beachten Sie, dass der Name der PostgreSQL-Rolle und das Kennwort, das Sie für den * Datenbankserver * festgelegt haben, mit denen identisch sein sollten, die Sie in der PostgreSQL-Installation des * App-Servers * festgelegt haben.

Schritt 1 - Erstellen eines Benutzers für die SSH-Tunnel

SSH-Tunnel sind verschlüsselte Verbindungen, die Daten von einem Port auf einem Server an einen Port auf einem anderen Server senden können, sodass es so aussieht, als würde ein Empfangsprogramm auf dem zweiten Server auf dem ersten Server ausgeführt. Ein dedizierter Benutzer für die SSH-Tunnel trägt zur Verbesserung der Sicherheit Ihres Setups bei: Sollte ein Angreifer Zugriff auf den * sammy * -Benutzer auf einem Ihrer Server erhalten, kann er im dreistufigen Setup nicht auf die anderen Server zugreifen . Wenn ein Angreifer Zugriff auf den * tunnel * -Benutzer erhält, kann er weder Dateien im Rails-App-Verzeichnis bearbeiten noch den Befehl + sudo + verwenden.

Erstellen Sie auf jedem Server einen zusätzlichen Benutzer mit dem Namen * tunnel *. Die einzige Funktion des * tunnel * -Benutzers besteht darin, SSH-Tunnel zu erstellen, um die Kommunikation zwischen den Servern zu erleichtern. Geben Sie daher im Gegensatz zu * sammy * keine * tunnel * + sudo + -Privilegien. Außerdem sollte der * tunnel * -Benutzer keinen Schreibzugriff auf das Rails-App-Verzeichnis haben. Führen Sie auf jedem Server den folgenden Befehl aus, um den Benutzer * tunnel * hinzuzufügen:

sudo adduser tunnel

Wechseln Sie auf dem * Webserver * zum * Tunnel * -Benutzer.

sudo su tunnel

Generieren Sie als * tunnel * -Benutzer ein SSH-Schlüsselpaar:

ssh-keygen

Speichern Sie den Schlüssel am Standardspeicherort und erstellen Sie keine Passphrase für die Schlüssel, da dies die spätere Authentifizierung erschweren könnte, wenn Sie SSH-Tunnel zwischen den Servern erstellen.

Kehren Sie nach dem Erstellen des Schlüsselpaars zum Benutzer * sammy * zurück:

exit

Wechseln Sie nun zum * App-Server * und führen Sie die gleichen Befehle erneut aus:

sudo su tunnel
ssh-keygen
exit

Sie haben jetzt alle Benutzer konfiguriert, die Sie für den Rest des Lernprogramms benötigen. Net, Sie werden einige Änderungen an der Datei "+ / etc / hosts +" für jeden * tunnel * -Benutzer vornehmen, um den Prozess der Erstellung der SSH-Tunnel zu optimieren.

Schritt 2 - Konfigurieren der Hosts-Datei

In diesem Lernprogramm müssen Sie häufig in einem Befehl auf die IP-Adressen des * App-Servers * oder des * Datenbank-Servers * verweisen. Anstatt sich diese IP-Adressen jedes Mal merken und eingeben zu müssen, können Sie die privaten IP-Adressen * app-server * und * database-server * zu den + / etc / hosts + -Dateien jedes Servers hinzufügen. Auf diese Weise können Sie ihre Namen in nachfolgenden Befehlen anstelle ihrer Adressen verwenden und die Einrichtung von SSH-Tunneln erheblich vereinfachen.

Beachten Sie, dass Sie in diesem Lernprogramm zur Vereinfachung die privaten IP-Adressen von * app-server * und * database-server * der Datei "+ / etc / hosts " in jedem der drei Ordner hinzufügen müssen Server. Obwohl es technisch nicht erforderlich ist, die privaten IP-Adressen des * App-Servers * oder * Datenbank-Servers * zu den eigenen ` hosts +` - Dateien hinzuzufügen, verursacht dies keine Probleme. Die hier beschriebene Methode wurde einfach aus Gründen der Schnelligkeit und Bequemlichkeit gewählt.

Ermitteln Sie zunächst die privaten IP-Adressen Ihres * App-Servers * und * Datenbank-Servers *. Wenn Sie DigitalOcean Droplets verwenden, navigieren Sie zu Ihrer Systemsteuerung und klicken Sie auf die Namen dieser Droplets. Auf jeder Droplet-spezifischen Seite werden sowohl die öffentlichen als auch die privaten IP-Adressen oben auf der Seite angezeigt.

Öffnen Sie dann auf jedem Server die Datei "+ / etc / hosts +" mit Ihrem bevorzugten Texteditor und fügen Sie die folgenden Zeilen hinzu:

sudo nano /etc/hosts

/ etc / hosts

. . .
app-server
database-server

Wenn Sie diese Zeilen zu dieser Datei auf jedem Server hinzufügen, können Sie die Namen * app-server * und * database-server * in Befehlen verwenden, die normalerweise die Verwendung der IP-Adressen dieser Server erfordern. Mit dieser Funktion richten Sie die SSH-Schlüssel ein, damit jeder Ihrer * Tunnel * -Benutzer eine Verbindung zu Ihren anderen Servern herstellen kann.

Schritt 3 - SSH-Anmeldungen einrichten

Nachdem Sie auf allen drei Servern einen * tunnel * -Nutzer und eine aktualisierte + / etc / hosts + - Datei haben, können Sie SSH-Verbindungen zwischen diesen Servern herstellen.

Stellen Sie sich die drei Ebenen wie eine Pyramide vor, mit dem * Datenbankserver * unten, dem * App-Server * in der Mitte und dem * Webserver * oben. Der * App-Server * muss eine Verbindung zum * Datenbank-Server * herstellen können, um auf die für die Rails-App erforderlichen Daten zugreifen zu können, und der * Web-Server * muss eine Verbindung zum * App-Server * herstellen können es hat den Benutzern etwas zu präsentieren.

Sie müssen also nur den öffentlichen SSH-Schlüssel jedes * Tunnel * -Nutzers zum Server "darunter" hinzufügen, dh, Sie müssen den öffentlichen Schlüssel des * Webservers * * Tunnel * -Nutzers zum * App-Server * hinzufügen und den hinzufügen * App-Server * * öffentlichen Schlüssel des Benutzers zum * Datenbank-Server * tunneln. Auf diese Weise können Sie verschlüsselte SSH-Tunnel zwischen den Ebenen einrichten und verhindern, dass Lauscher im Netzwerk den Datenverkehr zwischen ihnen lesen.

Um diesen Vorgang zu starten, kopieren Sie den öffentlichen Schlüssel des * tunnel * -Benutzers auf dem * Webserver * unter + / home / tunnel / .ssh / id_rsa.pub + in das `+ / home / tunnel /. ssh / authorized_keys + `Datei auf dem * App-Server *.

Zeigen Sie auf dem * Webserver * den öffentlichen Schlüssel des * Tunnelnutzers * im Terminal mit dem folgenden Befehl an:

sudo cat /home/tunnel/.ssh/id_rsa.pub

Wählen Sie die Textausgabe aus und kopieren Sie sie in die Zwischenablage Ihres Systems.

Stellen Sie in einer separaten Terminalsitzung eine SSH-Verbindung zum * App-Server * her und wechseln Sie zum Tunnelbenutzer:

sudo su tunnel

Hängen Sie den Schlüssel in Ihrer System-Zwischenablage an die Datei "+ authorized_keys" auf dem * App-Server * an. Sie können dazu den folgenden Befehl in einem Schritt verwenden. Denken Sie daran, "+ tunnel_ssh_publickey_copied_from_web_server +" durch den öffentlichen Schlüssel in der Zwischenablage Ihres Systems zu ersetzen:

echo "" >> /home/tunnel/.ssh/authorized_keys

Ändern Sie anschließend die Berechtigungen für die Datei "+ authorized_keys +", um den unbefugten Zugriff darauf zu verhindern:

chmod 600 /home/tunnel/.ssh/authorized_keys

Kehren Sie dann zum Benutzer * sammy * zurück:

exit

Zeigen Sie als Nächstes den öffentlichen Schlüssel des * tunnel * -Benutzers auf dem * App-Server * an, der sich unter + / home / tunnel / .ssh / id_rsa.pub + befindet, und fügen Sie ihn in `+ / home / tunnel / ein. ssh / authorized_keys + `Datei auf dem * Datenbank-Server *:

sudo cat /home/tunnel/.ssh/id_rsa.pub
sudo su tunnel

Da Sie auf dem * Datenbankserver * kein SSH-Schlüsselpaar generiert haben, müssen Sie den Ordner "+ / home / tunnel / .ssh +" erstellen und seine Berechtigungen anpassen:

mkdir /home/tunnel/.ssh
chmod 700 /home/tunnel/.ssh

Fügen Sie anschließend den öffentlichen Schlüssel des * App-Servers * zur Datei "+ authorized_keys +" hinzu und passen Sie die Berechtigungen an:

echo "" >> /home/tunnel/.ssh/authorized_keys
chmod 600 /home/tunnel/.ssh/authorized_keys

Kehren Sie dann zum Benutzer * sammy * zurück:

exit

Testen Sie als Nächstes die erste Verbindung, indem Sie SSH verwenden, um eine Verbindung mit dem * App-Server * von Ihrem * Web-Server * als * Tunnel * -Benutzer herzustellen:

sudo su tunnel
ssh tunnel@app-server

Wenn Sie das erste Mal eine Verbindung vom * Webserver * zum * App-Server * herstellen, werden Sie in einer Meldung aufgefordert, zu bestätigen, dass dem Computer, mit dem Sie eine Verbindung herstellen, vertraut werden kann. Geben Sie "yes" ein, um die Authentizität des * App-Servers * zu akzeptieren:

OutputThe authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)?

Sie sehen das Begrüßungsbanner vom * App-Server * und die Eingabeaufforderung zeigt an, dass Sie am * App-Server * angemeldet sind. Dies bestätigt, dass die SSH-Verbindung vom * Web-Server * zum * App-Server * korrekt funktioniert.

Beenden Sie die SSH-Verbindung zum * App-Server * und beenden Sie dann den * Tunnel * -Benutzer, um zum * sammy * -Benutzer Ihres * Webservers * zurückzukehren:

exit
exit

Führen Sie als Nächstes dieselben Schritte aus, um die SSH-Verbindung vom * App-Server * zum * Datenbank-Server * zu testen:

sudo su tunnel
ssh tunnel@database-server

Akzeptieren Sie auch die Authentizität des * Datenbank-Servers *. Wenn Sie das Begrüßungsbanner und die Eingabeaufforderung vom * Datenbankserver * sehen, wissen Sie, dass die SSH-Verbindung vom * App-Server * zum * Datenbankserver * wie erwartet funktioniert.

Beenden Sie die SSH-Verbindung zum * Datenbankserver * und anschließend den * Tunnel * -Benutzer:

exit
exit

Die in diesem Schritt eingerichteten SSH-Verbindungen bilden die Grundlage für die SSH-Tunnel, die eine sichere Kommunikation zwischen Ihren drei Serverebenen ermöglichen. In ihrer aktuellen Form sind diese Verbindungen jedoch anfällig für Abstürze und daher nicht so zuverlässig wie sie sein könnten. Indem Sie zusätzliche Software installieren und den Tunnel so konfigurieren, dass er als Dienst fungiert, können Sie diese Sicherheitsanfälligkeiten verringern.

Schritt 4 - Einrichten eines beständigen SSH-Tunnels zum Datenbankserver

Im letzten Schritt haben Sie von einem lokalen Server aus auf die Eingabeaufforderung eines Remoteservers zugegriffen. Mit einem SSH-Tunnel können Sie viel mehr tun, indem Sie den Datenverkehr von den Ports auf dem lokalen Host zu den Ports auf dem Remote-Host tunneln. Hier verwenden Sie einen SSH-Tunnel, um die Verbindung zwischen Ihrem * App-Server * und dem * Datenbank-Server * zu verschlüsseln.

Wenn Sie alle Voraussetzungen für dieses Tutorial erfüllt haben, haben Sie PostgreSQL sowohl auf dem * App-Server * als auch auf dem * Datenbank-Server * installiert. Um einen Konflikt bei den Portnummern zu vermeiden, müssen Sie den SSH-Tunnel zwischen diesen Servern so konfigurieren, dass Verbindungen vom Port "+ 5433 " des * App-Servers * zum Port " 5432 +" auf dem * Datenbankserver * weitergeleitet werden. Später konfigurieren Sie Ihre Rails-Anwendung (gehostet auf Ihrem * App-Server *) neu, um die PostgreSQL-Instanz zu verwenden, die auf dem * Datenbank-Server * ausgeführt wird.

Wechseln Sie als * sammy * Benutzer auf dem * App-Server * zu dem * tunnel * Benutzer, den Sie in Schritt 1 erstellt haben:

sudo su tunnel

Führen Sie den Befehl + ssh + mit den folgenden Flags und Optionen aus, um den Tunnel zwischen dem * App-Server * und dem * Datenbank-Server * zu erstellen:

ssh -f -N -L 5433:localhost:5432 tunnel@database-server
  • Die Option "+ -f " sendet " ssh +" in den Hintergrund. Auf diese Weise können Sie neue Befehle in Ihrer vorhandenen Eingabeaufforderung ausführen, während der Tunnel weiterhin als Hintergrundprozess ausgeführt wird.

  • Die Option "+ -N " weist " ssh +" an, keinen Remote-Befehl auszuführen. Dies wird hier verwendet, da Sie nur Ports weiterleiten möchten.

  • Der Option "+ -L " folgt der Konfigurationswert "+5433: localhost: 5432 +". Dies gibt an, dass der Datenverkehr von Port " 5433 " auf der lokalen Seite (dem * App-Server *) an den Port " 5432 +" von * localhost * auf dem Remote-Server (dem * Datenbank-Server *) weitergeleitet wird. Beachten Sie, dass * localhost * hier aus Sicht des Remote-Servers ist.

  • Der letzte Teil des Befehls, + tunnel @ database-server +, gibt den Benutzer und den Remote-Server an, zu dem eine Verbindung hergestellt werden soll.

Kehren Sie nach dem Aufbau des SSH-Tunnels zum Benutzer * sammy * zurück:

exit

Zu diesem Zeitpunkt läuft der Tunnel, aber es wird nichts beobachtet, um sicherzustellen, dass er in Betrieb bleibt. Wenn der Prozess abstürzt, bricht der Tunnel ab, die Rails-App kann nicht mehr mit ihrer Datenbank kommunizieren und es werden Fehler angezeigt.

Töte den Tunnel, den du für den Moment erstellt hast, da wir einen zuverlässigeren Aufbau machen werden. Da sich die Verbindung im Hintergrund befindet, müssen Sie die Prozess-ID ermitteln, um sie zu beenden. Da jeder Tunnel vom Benutzer * tunnel * erstellt wird, können Sie seine Prozess-ID ermitteln, indem Sie die aktuellen Prozesse auflisten und die Ausgabe nach dem Schlüsselwort "tunnel" filtern:

ps axu | grep tunnel

Dies wird so etwas wie die Ausgabe unten zurückgeben:

Outputtunnel     0.0  0.1  44920   692 ?        Ss   14:12   0:00 ssh -f -N -L 5433:localhost:5432 tunnel@database-server
sammy    21816  0.0  0.2  12916  1092 pts/0    S+   14:12   0:00 grep --color=auto tunnel

Stoppen Sie den Prozess, indem Sie den Befehl + kill + gefolgt von seiner Prozess-ID ausführen:

sudo kill

Um eine dauerhafte SSH-Verbindung zwischen dem Anwendungsserver und der Datenbank aufrechtzuerhalten, installieren Sie "+ autossh ". ` autossh +` ist ein Programm, das eine SSH-Verbindung startet, überwacht und neu startet, falls die Verbindung ausfällt oder der Datenverkehr unterbrochen wird:

sudo apt-get install autossh

https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files [+ systemd + ist die Standardeinstellung init system unter Ubuntu], was bedeutet, dass Prozesse nach dem Systemstart verwaltet werden. Sie können "+ systemd " verwenden, um einen Dienst zu erstellen, der Ihren SSH-Tunnel verwaltet und automatisch startet, wenn der Server neu gestartet wird. Erstellen Sie dazu eine Datei mit dem Namen " db-tunnel.service " im Verzeichnis " / lib / systemd / system / ", dem Standardverzeichnis, in dem die Unit-Dateien " systemd +" gespeichert sind:

sudo nano /lib/systemd/system/db-tunnel.service

Fügen Sie der neuen Datei den folgenden Inhalt hinzu, um einen Dienst für die Verwaltung von "+ systemd +" zu konfigurieren:

/lib/systemd/system/db-tunnel.service

[Unit]
Wants=network-online.target
After=network-online.target

[Service]
User=tunnel
WorkingDirectory=/home/tunnel
ExecStart=/bin/bash -lc 'autossh -N -L 5433:localhost:5432 tunnel@database-server'
Restart=always
StandardInput=null
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
KillMode=process

[Install]
WantedBy=multi-user.target

Die Schlüsselzeile hier ist "+ ExecStart ". Dies gibt den vollständigen Pfad zum Befehl und die Argumente an, die ausgeführt werden müssen, um den Prozess zu starten. Hier startet es eine neue ` bash ` Shell und führt dann das ` autossh +` Programm aus.

Speichern und schließen Sie die Datei und laden Sie dann die + systemd + - Konfiguration erneut, um sicherzustellen, dass die neue Servicedatei übernommen wird:

sudo systemctl daemon-reload

Aktivieren Sie den Dienst "+ db-tunnel +", damit der Tunnel zum * Datenbank-Server * automatisch startet, wenn der Server hochfährt:

sudo systemctl enable db-tunnel.service

Starten Sie dann den Dienst:

sudo systemctl start db-tunnel.service

Führen Sie den folgenden Befehl erneut aus, um zu überprüfen, ob der Tunnel aktiv ist:

ps axu | grep tunnel

In der Ausgabe sehen Sie, dass diesmal mehr Prozesse ausgeführt werden, da + autossh + jetzt den Tunnel überwacht:

Outputtunnel   25925  0.0  0.1   4376   704 ?        Ss   14:45   0:00 /usr/lib/autossh/autossh -N -L 5432:localhost:5432 tunnel@database-server
tunnel   25939  0.2  1.0  44920  5332 ?        S    14:45   0:00 /usr/bin/ssh -L 61371:127.0.0.1:61371 -R 61371:127.0.0.1:61372 -N -L 5432:localhost:5432 tunnel@database-server
sammy    25941  0.0  0.2  12916  1020 pts/0    S+   14:45   0:00 grep --color=auto tunnel

Jetzt, da der Tunnel läuft, können Sie die Verbindung zum * Datenbank-Server * mit + psql + testen, um sicherzustellen, dass er korrekt funktioniert.

Starten Sie den + psql-Client und teilen Sie ihm mit, eine Verbindung zu` + localhost` herzustellen. Sie müssen außerdem den Port "+ 5433 +" angeben, um über den SSH-Tunnel eine Verbindung zur PostgreSQL-Instanz auf dem * Datenbankserver * herzustellen. Geben Sie den zuvor erstellten Datenbanknamen an und geben Sie das Kennwort ein, das Sie für den Datenbankbenutzer erstellt haben, wenn Sie dazu aufgefordert werden:

psql -hlocalhost -p5433

Wenn Sie so etwas wie die folgende Ausgabe sehen, wurde die Datenbankverbindung korrekt eingerichtet:

Outputpsql (9.5.10)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

sammy=#

Um die PostgreSQL-Eingabeaufforderung zu schließen, geben Sie "+ \ a " ein und drücken Sie " ENTER".

Endlich haben Sie einen beständigen, zuverlässigen SSH-Tunnel, der den Verkehr zwischen Ihrem * App-Server * und * Datenbank-Server * verschlüsselt. Die Sicherheitsfunktionen des Tunnels sind von zentraler Bedeutung, da über diesen Tunnel die Rails-App auf Ihrem * App-Server * mit der PostgreSQL-Instanz auf Ihrem * Datenbankserver * kommuniziert.

Schritt 5 - Rails für die Verwendung einer entfernten Datenbank konfigurieren

Nachdem der Tunnel vom * App-Server * zum * Datenbank-Server * eingerichtet wurde, können Sie ihn als sicheren Kanal für Ihre Rails-App verwenden, um über den Tunnel eine Verbindung zur PostgreSQL-Instanz auf dem * Datenbank-Server * herzustellen. .

Öffnen Sie die Datenbankkonfigurationsdatei der Anwendung:

nano /home/sammy//config/database.yml

Aktualisieren Sie den Abschnitt "+ production +", sodass die Portnummer als Umgebungsvariable angegeben wird. Es sollte jetzt ungefähr so ​​aussehen:

/home/sammy/appname/config/database.yml

. . .
production:
 <<: *default
 host: localhost
 adapter: postgresql
 encoding: utf8
 database: appname_production
 pool: 5
 username: <%= ENV['APPNAME_DATABASE_USER'] %>
 password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>

Speichern und schließen Sie diese Datei, öffnen Sie dann die Datei + .rbenv-vars + im Anwendungsverzeichnis und bearbeiten Sie die Umgebungsvariablen:

nano /home/sammy//.rbenv-vars

Wenn Sie einen anderen Namen und ein anderes Kennwort für die PostgreSQL-Rolle auf dem * Datenbankserver * festgelegt haben, ersetzen Sie diese jetzt (im folgenden Beispiel heißt die PostgreSQL-Rolle * sammy *). Fügen Sie außerdem eine neue Zeile hinzu, um den Datenbankport anzugeben. Nachdem Sie diese Änderungen vorgenommen haben, sollte Ihre + .rbenv-vars + Datei folgendermaßen aussehen:

/home/sammy/appname/.rbenv-vars

SECRET_KEY_BASE=
_DATABASE_USER=
_DATABASE_PASSWORD=
_DATABASE_PORT=5433

Speichern und schließen Sie diese Datei, wenn Sie fertig sind.

Da Sie jetzt die PostgreSQL-Instanz auf dem * Datenbankserver * anstatt auf dem * App-Server * verwenden, auf dem Sie Ihre Rails-App bereitgestellt haben, müssen Sie die Datenbank erneut einrichten.

Navigieren Sie auf dem * App-Server * zum Verzeichnis Ihrer App und führen Sie den Befehl "+ rake +" aus, um die Datenbank einzurichten:

cd /home/sammy/
rake db:setup

Sobald dieser Befehl ausgeführt wurde, beginnt Ihre Rails-App über einen verschlüsselten SSH-Tunnel mit der Kommunikation mit der PostgreSQL-Instanz auf dem * Datenbankserver *. Als nächstes konfigurieren Sie Puma als "+ systemd +" - Dienst, um die Verwaltung zu vereinfachen.

Schritt 6 - Konfigurieren und Starten von Puma

Ähnlich wie Sie in Schritt 4 den Dienst "+ db-tunnel " eingerichtet haben, konfigurieren Sie " systemd +" so, dass Puma (die Serversoftware, die Sie als Teil der Voraussetzungen auf dem * App-Server * installiert haben) als Dienst ausgeführt wird . Wenn Sie Puma als Dienst ausführen, wird es automatisch gestartet, wenn der Server gestartet wird, oder es wird automatisch neu gestartet, wenn er abstürzt. Dadurch wird Ihre Bereitstellung robuster.

Erstellen Sie eine neue Datei mit dem Namen "+ puma.service " im Verzeichnis " / lib / systemd / system / +":

sudo nano /lib/systemd/system/puma.service

Fügen Sie der neuen Datei den folgenden Inhalt hinzu, der von Pumas + systemd + Dokumentation angepasst wurde. Achten Sie darauf, die hervorgehobenen Werte in den Anweisungen "+ User", "+ Working Directory" und "+ ExecStart" zu aktualisieren, um Ihre eigene Konfiguration widerzuspiegeln:

/lib/systemd/system/puma.service

[Unit]
Description=Puma HTTP Server
After=network.target

[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple

# Preferably configure a non-privileged user
User=

# The path to the puma application root
# Also replace the "<WD>" place holders below with this path.
WorkingDirectory=/home//

# Helpful for debugging socket activation, etc.
# Environment=PUMA_DEBUG=1

Environment=RAILS_ENV=production

# The command to start Puma.
ExecStart=/home//.rbenv/bin/rbenv exec bundle exec puma -b tcp://127.0.0.1:9292

Restart=always

[Install]
WantedBy=multi-user.target

Speichern und schließen Sie die Datei. Laden Sie dann + systemd + neu, aktivieren Sie den Puma-Dienst und starten Sie Puma:

sudo systemctl daemon-reload
sudo systemctl enable puma.service
sudo systemctl start puma.service

Stellen Sie anschließend sicher, dass Puma ausgeführt wird, indem Sie den Status des Dienstes überprüfen:

sudo systemctl status puma.service

Wenn es ausgeführt wird, sehen Sie eine Ausgabe ähnlich der folgenden:

Outputpuma.service - Puma HTTP Server
  Loaded: loaded (/lib/systemd/system/puma.service; enabled; vendor preset: enabled)
  Active: active (running) since Tue 2017-12-26 05:35:50 UTC; 1s ago
Main PID: 15051 (bundle)
   Tasks: 2
  Memory: 31.4M
     CPU: 1.685s
  CGroup: /system.slice/puma.service
          └─15051 puma 3.11.0 (tcp://127.0.0.1:9292) []

Dec 26 05:35:50 app systemd[1]: Stopped Puma HTTP Server.
Dec 26 05:35:50 app systemd[1]: Started Puma HTTP Server.
Dec 26 05:35:51 app rbenv[15051]: Puma starting in single mode...
Dec 26 05:35:51 app rbenv[15051]: * Version 3.11.0 (ruby 2.4.3-p205), codename: Love Song
Dec 26 05:35:51 app rbenv[15051]: * Min threads: 5, max threads: 5
Dec 26 05:35:51 app rbenv[15051]: * Environment: production

Verwenden Sie anschließend die Tastenkombination "+ locken ", um auf den Inhalt der Webseite zuzugreifen und ihn auszudrucken, damit Sie überprüfen können, ob die Seite korrekt angezeigt wird. Der folgende Befehl weist " curl " an, den Puma-Server, den Sie gerade auf * app-server * gestartet haben, an Port " 9292 +" aufzurufen:

curl localhost:9292/tasks

Wenn Sie so etwas wie den folgenden Code sehen, wird bestätigt, dass sowohl Puma als auch die Datenbankverbindung korrekt funktionieren:

Output...

<h1>Tasks</h1>

<table>
 <thead>
   <tr>
     <th>Title</th>
     <th>Note</th>
     <th colspan="3"></th>
   </tr>
 </thead>

 <tbody>
 </tbody>
</table>

...

Sobald Sie bestätigen können, dass Ihre Rails-App von Puma bereitgestellt wird und ordnungsgemäß für die Verwendung einer entfernten PostgreSQL-Instanz auf dem * Datenbankserver * konfiguriert ist, können Sie mit dem Einrichten des SSH-Tunnels zwischen dem * Webserver * und dem fortfahren * App-Server *.

Schritt 7 - Einrichten und Beibehalten des SSH-Tunnels zum App Server

Jetzt, da der * App-Server * läuft, können Sie ihn mit dem * Web-Server * verbinden. Ähnlich wie in Schritt 4, richten Sie dazu einen weiteren SSH-Tunnel ein. Durch diesen Tunnel kann Nginx auf dem * Webserver * eine sichere Verbindung über eine verschlüsselte Verbindung zu Puma auf dem * App-Server * herstellen.

Beginnen Sie mit der Installation von + autossh + auf dem * Webserver *:

sudo apt-get install autossh

Erstellen Sie eine neue Datei mit dem Namen "+ app-tunnel.service " im Verzeichnis " / lib / systemd / system / +":

sudo nano /lib/systemd/system/app-tunnel.service

Fügen Sie dieser Datei den folgenden Inhalt hinzu. Auch hier ist die Schlüsselzeile diejenige, die mit "+ ExecStart " beginnt. Hier leitet diese Zeile den Port " 9292 " auf dem * Web-Server * an den Port " 9292 +" auf dem * App-Server * weiter, auf dem Puma lauscht:

/lib/systemd/system/app-tunnel.service

[Unit]
StopWhenUnneeded=true
Wants=network-online.target
After=network-online.target

[Service]
User=tunnel
WorkingDirectory=/home/tunnel
ExecStart=/bin/bash -lc 'autossh -N -L 9292:localhost:9292 tunnel@app-server'
Restart=always
StandardInput=null
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
KillMode=process

[Install]
WantedBy=multi-user.target

Laden Sie + systemd + neu, damit es die neue Servicedatei liest, und aktivieren und starten Sie den Dienst + app-tunnel +:

sudo systemctl daemon-reload
sudo systemctl enable app-tunnel.service
sudo systemctl start app-tunnel.service

Überprüfen Sie, ob der Tunnel in Betrieb ist:

ps axu | grep tunnel

Sie sollten etwas sehen, das der Ausgabe unten ähnelt:

Outputtunnel   19469  0.0  0.1   4376   752 ?        Ss   05:45   0:00 /usr/lib/autossh/autossh -N -L 9292:localhost:9292 tunnel@app-server
tunnel   19482  0.5  1.1  44920  5568 ?        S    05:45   0:00 /usr/bin/ssh -L 54907:127.0.0.1:54907 -R 54907:127.0.0.1:54908 -N -L 9292:localhost:9292 tunnel@app-server
sammy    19484  0.0  0.1  12916   932 pts/0    S+   05:45   0:00 grep --color=auto tunnel

Diese gefilterte Prozessauflistung zeigt, dass "+ autossh " ausgeführt wird und ein weiterer " ssh +" - Prozess gestartet wurde, der den eigentlichen verschlüsselten Tunnel zwischen "* web-server " und " app-server *" erstellt.

Ihr zweiter Tunnel ist jetzt aktiv und verschlüsselt die Kommunikation zwischen Ihrem * Web-Server * und * App-Server *. Alles, was Sie tun müssen, um Ihre dreistufige Rails-App zum Laufen zu bringen, ist, Nginx so zu konfigurieren, dass Anforderungen an Puma weitergeleitet werden.

Schritt 8 - Konfigurieren von Nginx

Zu diesem Zeitpunkt sind alle erforderlichen SSH-Verbindungen und -Tunnel eingerichtet und jede Ihrer drei Serverebenen kann miteinander kommunizieren. Der letzte Teil dieses Puzzles besteht darin, Nginx so zu konfigurieren, dass Anforderungen an Puma gesendet werden, damit das Setup voll funktionsfähig ist.

Erstellen Sie auf dem * Webserver * eine neue Nginx-Konfigurationsdatei unter + / etc / nginx / sites-available / +:

sudo nano /etc/nginx/sites-available/

Fügen Sie der Datei den folgenden Inhalt hinzu. Diese Nginx-Konfigurationsdatei ähnelt der, die Sie verwendet haben, als Sie unserem Leitfaden unter https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx gefolgt sind -on-ubuntu-14-04 # install-and-configure-nginx [Bereitstellen einer Rails-App mit Puma und Nginx]. Der Hauptunterschied ist der Speicherort der vorgelagerten App. Anstatt die lokale Socket-Datei zu verwenden, verweist diese Konfiguration Nginx auf den SSH-Tunnel, der an Port + 9292 + empfangsbereit ist:

/ etc / nginx / sites-available / appname

upstream app {
   server 127.0.0.1:9292;
}

server {
   listen 80;
   server_name localhost;

   root /home/sammy//public;

   try_files $uri/index.html $uri @app;

   location @app {
       proxy_pass http://app;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_redirect off;
   }

   error_page 500 502 503 504 /500.html;
   client_max_body_size 4G;
   keepalive_timeout 10;
}

Speichern und schließen Sie diese Datei, aktivieren Sie die Site und aktivieren Sie die Änderungen.

Entfernen Sie zunächst die Standardwebsite:

sudo rm /etc/nginx/sites-enabled/default

Wechseln Sie in das Verzeichnis "+ sites-enabled +" von Nginx:

cd /etc/nginx/sites-enabled

Erstellen Sie im Verzeichnis "+ sites-enabled" einen symbolischen Link zu der Datei, die Sie gerade im Verzeichnis "+ sites-available +" erstellt haben:

sudo ln -s /etc/nginx/sites-available/

Testen Sie Ihre Nginx-Konfiguration auf Syntaxfehler:

sudo nginx -t

Wenn Fehler gemeldet werden, gehen Sie zurück und überprüfen Sie Ihre Datei, bevor Sie fortfahren.

Wenn Sie bereit sind, starten Sie Nginx neu, damit es Ihre neue Konfiguration liest:

sudo systemctl restart nginx

Wenn Sie das Puma-Tutorial in den Voraussetzungen befolgt hätten, hätten Sie Nginx und PostgreSQL auf dem * App-Server * installiert. Beide wurden durch separate Instanzen ersetzt, die auf den beiden anderen Servern ausgeführt werden, sodass diese Programme redundant sind. Daher sollten Sie diese Pakete vom * App-Server * entfernen:

sudo apt remove nginx
sudo apt remove postgresql

Stellen Sie nach dem Entfernen dieser Pakete sicher, dass Sie Ihre Firewall-Regeln aktualisieren, um zu verhindern, dass unerwünschter Datenverkehr auf diese Ports zugreift.

Ihre Rails-App ist jetzt in Produktion. Besuchen Sie die öffentliche IP Ihres * Webservers * in einem Webbrowser, um sie in Aktion zu sehen:

http:///tasks

Fazit

Mit diesem Tutorial haben Sie Ihre Rails-Anwendung in einer dreistufigen Architektur implementiert und die Verbindungen von Ihrem * Webserver * zum * App-Server * und vom * App-Server * zum * Datenbank-Server gesichert * mit verschlüsselten SSH-Tunneln.

Mit den verschiedenen Komponenten Ihrer Anwendung auf separaten Servern können Sie die optimalen Spezifikationen für jeden Server auswählen, basierend auf dem Datenverkehr, den Ihre Site empfängt. Der erste Schritt besteht darin, die vom Server verbrauchten Ressourcen zu überwachen. Anweisungen zum Überwachen der CPU-Auslastung Ihrer Server finden Sie unter our guide on CPU monitoring. Wenn Sie feststellen, dass die CPU- oder Speicherauslastung auf einer Ebene sehr hoch ist, können Sie die Größe des Servers allein auf dieser Ebene ändern. Weitere Hinweise zur Auswahl der Servergröße finden Sie in unserem Leitfaden unter https://www.digitalocean.com/community/tutorials/choosing-the-right-droplet-for-your-applications (Auswahl des richtigen Droplets für Ihre Anwendung).

Als unmittelbaren nächsten Schritt sollten Sie auch die Verbindung Ihrer Benutzer zum * Webserver * sichern, indem Sie ein SSL-Zertifikat auf dem * Webserver * installieren. Anweisungen hierzu finden Sie unter Nginx Let’s Encrypt tutorial. Weitere Informationen zur Verwendung von SSH-Tunneln finden Sie unter https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys#setting- Up-SSH-Tunnel [diese Anleitung].