Przekieruj wszystkie żądania http za Amazon ELB na https bez użycia if

27

Obecnie mam ELB obsługujący zarówno http://www.example.org, jak i https://www.example.org .

Chciałbym to skonfigurować, aby każde żądanie wskazujące na http://www.example.org było przekierowywane na https://www.example.org .

ELB wysyła żądania https jako żądania HTTP, więc używając:

server {
      listen         80;
       server_name    www.example.org;
       rewrite        ^ https://$server_name$request_uri? permanent;
}

nie będzie działać, ponieważ żądania wysłane do https://www.example.org będą nadal wysyłane do portu 80 na nginx.

Wiem, że można to przepisać jako

server {
      listen         80;
      server_name    www.example.org;
      if ($http_x_forwarded_proto != "https") {
          rewrite ^(.*)$ https://$server_name$1 permanent;
      }
}

Ale wszystko, co przeczytałem, mówi, że ifnależy unikać za wszelką cenę w konfiguracji nginx, i tak byłoby w przypadku każdego pojedynczego żądania. Oznacza to również, że muszę skonfigurować specjalną oddzielną konfigurację dla kontroli poprawności ( jak opisano tutaj : „… gdy jesteś za ELB, gdzie ELB działa jako punkt końcowy HTTPS i wysyła tylko ruch HTTP do twojego serwera, przerwać zdolność do odpowiedzi za pomocą odpowiedzi HTTP 200 OK w celu sprawdzenia poprawności, którego potrzebuje ELB ”).

Zastanawiam się nad umieszczeniem loginu w kodzie aplikacji sieciowej zamiast konfiguracji nginx (i na potrzeby tego pytania załóżmy, że jest to aplikacja oparta na Django), ale nie jestem pewien, czy byłoby to większe obciążenie ogólne niż if konfiguracja w.

Jordan Reiter
źródło
Cześć, czy możesz mi powiedzieć, gdzie umieszczasz ten kod?
YuAn Shaolin Maculelê Lai
@ YuAnShaolinMaculelêLai Sure. Są to pliki konfiguracyjne dla nginx, więc po prostu umieściłem kod w pliku w /etc/nginx/conf.d/. Zazwyczaj nazywam plik nazwa_domeny.conf, gdzie „nazwa_domeny” to domena danej witryny. Możesz nazwać plik, jak chcesz, pod warunkiem, że kończy się na .conf.
Jordan Reiter
Dziękuję Ci bardzo. Próbowałem utworzyć nowy plik .conf. Ale to nie działało dla mnie. Następnie umieszczam kod w pliku wygenerowanym z AWS w /etc/nginx/conf.d/. Teraz działa.
YuAn Shaolin Maculelê Lai

Odpowiedzi:

9

Jeśli tak działa poprawnie, nie bój się tego. http://wiki.nginx.org/IfIsEvil

Ważne jest, aby pamiętać, że zachowanie if nie jest niespójne, biorąc pod uwagę dwa identyczne żądania, losowo nie zawiedzie jednego i będzie działać na drugim, z odpowiednim testowaniem i zrozumieniem, czy można je zastosować . Jednak bardzo ważne są porady dotyczące stosowania innych dyrektyw, o ile są one dostępne.

ceejayoz
źródło
Ta strona mówi również, że „jeśli ma problemy, gdy jest używany w kontekście lokalizacji”. Wydaje mi się, że można zrobić to, czego potrzebują do robienia na zewnątrz location {}, w server {}zamian. (Ale proszę dać mi znać, jeśli jest to nieprawidłowe!)
Excalibur
15
  1. Skonfiguruj AWB ELB odwzorowujący ELB: 80 na instancję: 80 i ELB: 443 na instancję: 1443.
  2. Powiąż nginx, aby nasłuchiwać na portach 80 i 1443.
  3. Przekazywanie wniosków przybywających do portu 80 do portu 443.
  4. Kontrola stanu powinna mieć wartość HTTP: 1443. Odrzuca HTTP: 80, ponieważ przekierowanie 301.

konfiguracja łokcia aws

Konfiguracja NGINX

    server {
       listen         80;
       server_name    www.example.org;
       rewrite        ^ https://$server_name$request_uri? permanent;
    }

    server {
       listen         1443;
       server_name    www.example.org;
   } 
Nu Everest
źródło
co z ustawieniami kontroli stanu? czy mógłbyś również rozwinąć tę kwestię?
samkhan13
nie działało to przy sprawdzeniu helth ustawionym na http: 80, sprawdzenie poprawności kończy się niepowodzeniem.
samkhan13
2
Kontrola stanu zdrowia powinna być HTTP:1443. Odrzuca HTTP:80ponieważ przekierowanie 301.
cbron
to w większości działało dla mnie, ale linia przepisywania nie działała z moją domeną wieloznaczną. Ten inny post naprawił tę część: serverfault.com/questions/447258/…
Ron
9

To rozwiązanie wykorzystuje logikę warunkową, ale jak sugeruje przyjęta odpowiedź, również uważam, że jest to w porządku. Zobacz: /programming/4833238/nginx-conf-redirect-multiple-conditions

Nie wymaga to również otwierania żadnych dodatkowych portów w ustawieniach bezpieczeństwa aws dla obrazu. Możesz zakończyć ssl w AWS LB i skierować ruch https do portu http 80 w twojej instancji.

W tym przykładzie sprawdzanie poprawności LB trafia / kondycja na porcie 80, który kieruje do serwera aplikacji, więc sprawdzanie poprawności sprawdza zarówno nginx, jak i twoja aplikacja oddychają.

server {
  listen 80 default deferred;

  set $redirect_to_https 0;
  if ($http_x_forwarded_proto != 'https') {
    set $redirect_to_https 1;
  }
  if ($request_uri = '/health') {
    set $redirect_to_https 0;
  }
  if ($redirect_to_https = 1) {
    rewrite ^ https://www.example.com$request_uri? permanent;
  }
  ...
}
Jonny Mac
źródło
1
musi to być bardziej elegancki sposób
Edward
0

Możesz teraz utworzyć nowego nasłuchiwania w Ustawieniach modułu równoważenia obciążenia AWS, który przekierowuje port HTTP 80 do portu HTTPS 443. Nie musisz już dotykać konfiguracji nginx / apache.

Kenny Greulich
źródło
niestety nie jest jeszcze obsługiwane w Cloudformation
Aryeh Leib Taurog