Webserver.tips

Nginx als Gateway für AWS Lambda-Funktionen im VPC

Problem

nginx als Gateway

Die beliebten Lambda-Funktionen in AWS werden von Amazon nach und nach mit immer mehr sinnvollen Features ausgestattet. Seit einiger Zeit können Lambda Funktionen auch in einem VPC ausgeführt werden. Das ist sehr hilfreich, wenn man z.B. auf eine RDS Datenbank zugreifen will - die ja hoffentlich auch in einem VPC läuft.

Allerdings können Lambda-Funktionen in VPCs nicht mehr auf das Internet zugreifen. Das ist oft gewollt, aber ein unerwünschter Nebeneffekt ist, dass selbst AWS-Dienste wie SES (Simple Email Service) nicht mehr erreichbar sind, da deren APIs nur über das Internet erreichbar sind.

Amazon schlägt als Lösung vor, einen NAT-Gateway für das VPC einzurichten. Die NAT Gateways sind allerdings nicht ganz billig und eine solche Lösung ist für kleine bis mittlere Sendevolumen überdimensioniert.

Lösung

Es geht auch kostengünstiger: Wenn auf einer EC2-Instanz sowieso ein nginx läuft, dann kann man diesen als Reverse-Proxy benutzen, um die API Requests der Lambda-Funktion aus dem VPC an den jeweiligen Dienst weiterzuleiten. Hier eine Beispielkonfiguration für eine Node.js Lambda-Funktion und den AWS SES Service:

nginx

Für nginx ergänzen wir in der Konfiguration einen zusätzlichen server:

server {
  listen 80;
  server_name ip-172-31-24-100.eu-west-1.compute.internal;
  root "/usr/share/nginx/websites/ip-172-31-24-100.eu-west-1.compute.internal";

  location /SES/ {
    proxy_pass https://email.eu-west-1.amazonaws.com/;
  }
}

Dabei ist zu beachten, dass dieser Server aus dem VPN erreichbar ist, d.h. als servername wählt man den Namen, der auf die VPN IP zeigt. Den Namen finden man in der Beschreibung der EC2-Instanz:

Screenshot der EC2-Konsole, der Servername ist hervorgehoben

Für den Dienst, den man erreichen will, legt man eine location an. Darin konfiguriert man eine proxy_pass-Direktive für den Dienst, den man erreichen will, in unserem Fall SES, das unter https://email.eu-west-1.amazonaws.com/ zu erreichen ist.

Achtung: Auch wenn man gar keine Dateien ausliefern will, ist eine root-Direktive notwendig, damit nginx nicht einfach einen Fehler zurückliefert. Sie kann einfach auf ein leeres Verzeichnis zeigen.

Lambda-Funktion

In der Lambda-Funktion kann man für den E-Mail-Versand z.B. das Node.js Modul node-ses verwenden. Dies initialisiert man nun mit dem internen Namen des nginx-Servers:

const ses = require('node-ses');
const client = ses.createClient({
  amazon: 'http://ip-172-31-24-100.eu-west-1.compute.internal/SES/',
  key: '...',
  secret: '...'
});

Und damit ist auch schon alles erledigt: Die Lambda-Funktion greift auf nginx zu und nginx leitet die API-Requests an SES weiter.

@Digitalkapitaen

Ein Projekt von Digital Sailors