Grey padlocks at red fence - symbol of security

Zabezpieczenia instancji AWS: Security Groups

Jednym z elementów konfiguracji infrastruktury, o którym bardzo często się zapomina, są zabezpieczenia. Niejednokrotnie administratorzy skupiają się na dostarczeniu funkcjonalności i realizacji wymagań, a kwestie ochrony przed atakami traktowane są trochę na zasadzie jakoś to będzie. W Droptica często budujemy strony korporacyjne na Drupalu dla banków i dla dużych organizacji, dla których kwestie bezpieczeństwa pozostają niezwykle istotne. 

Jednak do zapewnienia minimum bezpieczeństwa nie potrzeba wcale wymyślnych mechanizmów - zacznijmy jednak od początku.

Filtrowanie ruchu sieciowego

Jednym ze sposobów zabezpieczania sieci i systemów przed intruzami są firewalle - narzędzia służące do blokowania niechcianych połączeń przychodzących i wychodzących oraz tym samym odmawianie żądań dostępu do sieci czy usługi uznanych za niebezpieczne.

Najprostszym typem zapory sieciowej jest filtr pakietów, który sprawdza adresy sieciowe i porty pakietów, aby ustalić, czy powinny zostać odrzucone bądź przepuszczone do maszyny docelowej. W takim rozwiązaniu firewall dysponuje zestawem reguł, które decydują o losie pakietu w zależności od kierunku połączenia (w szczególności, z jakiego adresu i na jaki adres jest ono kierowane), numeru portu sieciowego oraz jego typu (m.in. TCP, UDP lub ICMP).

AWS: Security Groups

Polityki Security Groups funkcjonują dokładnie tak samo, jak firewall filtrujący pakiety i służą do kontrolowania ruchu w sieci AWS. Amazon pozwala na zdefiniowanie reguł dla większości swoich produktów, które są wystawiane do sieci zewnętrznych.

W momencie uruchomienia nowej instancji EC2 administrator przypisuje do niej przynajmniej jedną politykę. Każdą z nich można modyfikować w dowolnym momencie istnienia - zmiany są zastosowywane automatycznie i natychmiastowo.

Amazon daje możliwość konfiguracji zarówno polityk dla ruchu przychodzącego jak i wychodzącego, przykład reguł dla naszego serwera testowego przedstawiony został na poniższym rysunku.

AWS Hosting Security Group example

Konfiguracja Security Groups

Głównym założeniem polityk Security Groups jest udostępnienie na zewnątrz tych usług, które tego wymagają. Powszechną praktyką jest uruchamianie na serwerach aplikacji pomocniczych (np. solr, redis, memcached) - te nie powinny być jednak udostępnione dla użytkowników. Dlatego też na początku należy zastanowić się, co powinno być widoczne dla innych.

W przypadku serwera WEB polityka otwartych portów może wyglądać na przykład tak:

  • SSH (22) - jeśli chcemy zdalnie zarządzać serwerem (można dopuścić tylko ruch z sieci wewnętrznej),
  • HTTP (80) - dla ruchu niezabezpieczonego,
  • HTTPS (443) - dla ruchu zabezpieczonego.

Oczywiście nie są to jedyne usługi. Czasami dochodzi potrzeba wystawienia serwera pocztowego (SMTP, IMAP) czy dedykowanych API (np. port 8080). Niemniej jednak jest to podstawowa zalecana konfiguracja wyjściowa.

Przykład przy użyciu Terraforma

Dobrą praktyką jest również stosowanie się do pomysłu przechowywania infrastruktury w postaci kodu - ułatwia to i przyśpiesza zarządzanie serwerami, dlatego też stosujemy takie podejście w Dropica. Przykładowy kod napisany w Terraformie, który służy do zarządzania Security Groups, prezentuje się następująco.

resource "aws_security_group" "web-sg" {
  name        = "web-sg"
  vpc_id      = "${aws_vpc.vpc.id}"
  description = "Allow incoming WEB connections"

  tags {
    Name = "web-sg"
  }

  # Allow incoming SSH
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow incoming HTTP
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow incoming HTTPS
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow incoming ICMP
  ingress {
    from_port   = -1
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  # Allow all outgoing traffic
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Na początku definiujemy podstawowe informacje, czyli nazwę, opis i identyfikator sieci, do którego będzie przypisana polityka. W dalszej kolejności dokładnie określamy filtry (wykorzystaliśmy te opisane z poprzedniej sekcji).

Wartości from_port oraz to_port pozwalają na zdefiniowanie zakresów, np. otwarcia wszystkich portów pomiędzy 8000 a 9000. Sekcje ingress dotyczą ruchu przychodzącego, zaś egress ruchu wychodzącego.

Podsumowanie

Security Groups nie są jakimś wyjątkowym mechanizmem, który uczyni serwery fortecą nie do zdobycia, ale pozwala nam ograniczyć widoczność tego, co nie powinno być dostępne publicznie. Często popełnianym błędem początkujących administratorów jest przypisanie domyślnych polityk do wszystkich usług - co prowadzi do udostępnienia wszystkich usług publicznych. Dlatego też warto zrozumieć i zgłębić ten temat.

3. Najlepsze praktyki zespołów programistycznych