Ein AWS-Problem, bei dem ich regelmäßig um Hilfe gebeten werde, klingt in der ersten Beschreibung meist so:
Ich habe hier was installiert (z.B. eine EC2 Instanz mit WebServer, eine RDS, ein ECS Cluster, oder …). Aber leider kann ich es nicht erreichen. Was ist der Grund?
Natürlich ist dieses Fehlerbild ziemlich allgemein und es gibt eine ganze Reihe möglicher Ursachen. Meist lässt sich das Problem dennoch recht schnell eingrenzen und dann auch beheben, wenn man ein Grundverständnis der beteiligten AWS-Dienste und -Ressourcen hat. Ich arbeite in solchen Fällen eine innere Checkliste ab, die die wichtigsten an einer TCP/IP-Verbindung beteiligten Infrastrukturkomponenten in AWS durchgeht.
Diese „Checkliste“ schreibe ich nun explizit auf, um dieser Fehlerklasse den Nimbus des Magischen zu nehmen. (Ein Kollege schrieb mir kürzlich: „Irgendwie ist das [AWS] alles ziemlich gruselig“).
Mein Vorgehen hat vermutlich viele Lücken, insofern bin ich für Verbesserungsvorschläge oder Alternativen dankbar.
Meine Checkliste:
- Funktioniert die Namensauflösung?
- Ist das Ziel adressierbar?
- Gibt es eine Netzwerk-Route von der Quelle zum Ziel?
- Gibt es eine Network-ACL, die gegen die Verbindung spricht?
- Gibt eine Security Group, die die Verbindung erlaubt?
- Lauscht der Dienst überhaupt auf dem/einem öffentlichen Interface?
Die Reihenfolge, in der ich die Punkte bearbeite, hängt in der Regel davon ab, welche Ursache ich vermute – ich arbeite dabei also wesentlich weniger systematisch, als ich mir selbst gerne vormachen würde.
Hier nun Erläuterungen zu den einzelnen Punkten im Detail:
Namensauflösung
Wenn die Zielressource über einen DNS Namen adressiert wird, probiere ich, ob sich dieser auflösen lässt. Das mache ich z.B. mit dem Kommandozeilen-Tool dig
. Je nachdem, was in der Umgebung zur Verfügung steht, tut es aber auch oft ein einfaches ping
zum ersten Validieren. Umgebung ist dabei auch ein wichtiges Stichwort, denn Namensauflösung ist durchaus abhängig davon, wo sie statt findet.
Im AWS-Kontext tritt dabei vor allem der „split-horizon“ an der AWS- bzw. VPC-Grenze auf: Der gleiche Domainname kann innerhalb von AWS zu einer privaten 10er IP-Adresse und außerhalb zu einer öffentlichen IP aufgelöst werden. Das kann besonders bei den default EC2-DNS-Namen verwirrend sein, die dem Muster ec2-public-ipv4-address.region.compute.amazonaws.com folgen. Der DNS-Name mit der öffentlichen IP muss nicht zur öffentlichen IP aufgelöst werden. Das Ganze ist dabei ein Feature zum (kosten-)effizienten Routen (AWS Dokumentation).
Am Ende dieses Checks sollte man also zuversichtlich sein, dass der Name in der richtigen Umgebung zur erwarteten IP auflöst.
Ist das Ziel adressierbar?
Damit eine direkte Verbindung zum Zielsystem aufgebaut werden kann, muss dessen IP-Adresse bekannt sein und im Adressraum des Quellsystems liegen. Konkret bedeutet das: Soll die Verbindung aus dem (oder „über“ das) Internet stattfinden, muss die Ziel-IP eine öffentliche sein und keine aus dem für private Netze reserviertem Raum (Häufig 10.*.*.*, es gibt aber weitere private Adressen).
Bei RDS heißt die Option zum Zuweisen einer öffentlichen Adresse „Publicly Accessible“. Bei EC2-Instanzen muss dafür eine öffentliche oder „elastic IP“ zugewiesen sein. Default-Werte dafür ergeben sich daraus, ob das Subnetz „öffentlich“ oder „privat“ ist.
Die globale Adressierbarkeit ist natürlich nicht immer wünschenswert. Wenn die Verbindung zwischen zwei Punkten innerhalb eines VPC (oder zwischen zwei mittels Peering verbundenen VPCs) stattfinden soll, reicht die private Adresse.
Häufig existiert auch eine extern adressierbare Schnittstelle wie ein Loadbalancer oder ein „Jump Host“, von dem aus die eigentlichen Ziele dann nur privat adressierbar sind.
Ein Mischfall sind Server, die nicht aus dem Internet adressierbar sein sollen, selbst aber Verbindungen „nach draußen“ initiieren können sollen. In diesem Fall reicht eine private Adresse, es braucht aber NAT.
Gibt es eine Route?
Um das Routing in AWS zu verstehen, ist es notwendig, etwas auszuholen. Mit Hilfe des Dienstes VPC (Virtual Private Cloud) kann man sehr flexibel die Struktur seinen Netzwerkes definieren. Die wichtigsten Bestandteile sind dabei:
- VPC ist ein virtuelles Netzwerk. Es ist jeweils an einen AWS-Account gebunden. Neben einem Namen ist die Kerneigenschaft eines VPC sein Adressraum oder auch CIDR-Block, z.b. 10.0.0.0/16. Hiermit wird festgelegt, welche IP-Adressen (und damit auch wieviele!) im VPC zur Verfügung stehen.
- Innerhalb eines VPC werden ein oder mehrere Subnetze (Subnet) angelegt. Jedem dieser Subnetze wird wieder ein CIDR-Block zugewiesen, der eine Teilmenge des Blocks des VPC ist. Jedes Subnetz liegt in genau einer Availability Zone – daher hat man es auch immer mit mehreren Subnetzen zu tun, wenn Ausfallsicherheit eine Rolle spielt.
- Jedes Subnetz verfügt implizit über einen Router. Wie bei einer Verkabelung im „echten“ Rechenzentrum bestimmt der Router, welche Pakete wohin transportiert werden. Dazu ist jedem Subnetz genau eine Routing-Tabelle zugewiesen. Dabei kann eine Routing-Tabelle aber mehreren Subnetzen zugewiesen sein. Das VPC hat automatisch eine „Haupt-Routing-Tabelle“, die allen Subnetzen zugewiesen ist, sofern nicht anders konfiguriert. Eine Routing-Tabelle ist dabei eine Liste von Routen. Eine Route hat jeweils ein Zieladressen-CIDR sowie ein Ziel. Für jede zu vermittelnde Verbindung zu einer IP-Adresse wird in der Routing Tabelle anhand des CIDR die spezifischste passende Route gewählt. Deren Ziel definiert, wohin eine Verbindung erstellt wird. Mögliche Ziele sind dabei:
- local für die Zustellung innerhalb des Netzes
- Internet Gateways für die Zustellung ins Internet
- Gateways für Peering
Die Tabelle eines Netzes, das aus dem Internet erreichbar ist, sieht dabei dann z.B. so aus:
Destination | Target |
---|---|
172.31.0.0/16 | local |
0.0.0.0/0 | igw-XXXXXXXX |
Es gibt also eine Route für die lokalen Adressen und eine Route für alles andere zum Internet-Gateway. Meiner Erfahrung nach fehlt häufig die zweite Zeile in der Tabelle, also das Routing zum Internet-Gateway für alle nicht lokalen Adressen.
Verhindert die Network ACL den Zugriff?
„Network access control lists“ (ACLs) sind eine optionale Sicherheitsschicht in VPCs bei Amazon. Es handelt sich um Firewalls auf Subnetzebene. Sie erlauben es, eingehenden und ausgehenden Netzwerkverkehr mit „allow“- und „deny“-Regeln zu filtern.
Ich erwähne sie hier nur der Vollständigkeit halber. Da sie per default „offen“ konfiguriert sind, sind sie kein typisches Problem bei ersten Schritten in AWS. In komplexeren, besser abgesicherten Setups lohnt sich aber ein genauerer Blick.
Security Groups
Ein wesentlich häufigerer Grund für Verbindungsprobleme sind meiner Erfahrung nach fehlerhafte Security Groups (SG). Auch SGs sind Firewalls, sie operieren aber auf Instanzebene, sind also ein oder mehreren EC2- oder RDS- (oder …) Instanzen zugeordnet.
Security Groups enthalten eine Liste von Regeln, die Verbindungen zulassen. Dabei bezieht sich jede Regel auf einen Port oder Port Range und eine Quelle. Die Quelle wird hier entweder über eine feste IP, einen IP-Range (CIDR notation) oder eine Referenz auf eine andere Security Group definiert.
Grade diese letzte Möglichkeit ist beim ersten Kontakt mit Security Groups nicht offensichtlich, aber notwendig für typische Setups. Ein solches ist, z.B. den Zugriff auf einen HTTP-Port von einem Amazon Loadbalancer (ELB) aus zuzulassen:
Port | Source |
---|---|
8080 | sg-XXXX |
Dabei ist die Security Group sg-XXXX dem Loadbalancer zugewiesen.
Lokale Probleme
Zu guter Letzt kann es sein, dass das Problem überhaupt nichts mit AWS zu tun hat. Einige Server lauschen per Default aus Sicherheitsgründen nur „lokal“, also auf dem Loopback-Device. Sie müssen dann explizit konfiguriert werden, auf anderen Interfaces zu lauschen. Häufig geschieht das durch Zuweisen der Bind-Adresse 0.0.0.0.
Eine andere lokale Fehlerquelle sind lokale Firewalls. Es lohnt sich also, einen Blick in iptables
, firewalld
oder Entsprechungen zu werfen.
Das war’s auch schon. Ich hoffe, meine Checkliste nützt dem ein oder der anderen.