Memungkinkan Enkripsi dengan proxy reverse nginx

45

pengantar

Saya memiliki server dev (saat ini menjalankan Ubuntu 14.04 LTS), yang telah saya gunakan untuk sementara waktu sekarang untuk hosting berbagai alat pengembangan pada port yang berbeda. Karena port-port itu sulit untuk diingat, saya telah memutuskan untuk menggunakan port 80 untuk semua layanan saya dan melakukan penerusan port secara internal, berdasarkan nama host.

Alih-alih menulis domain.com:5432, saya cukup mengaksesnya melalui sub.domain.com

Misalnya aplikasi X, yang menggunakan port 7547 dan berjalan pada sub.domain.com memiliki konfigurasi nginx berikut:

upstream sub {
    server 127.0.0.1:7547;
}

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    access_log /var/log/nginx/sub.log combined;
    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:7547;
            proxy_set_header Authorization "";
    }
}

Pertanyaan

Mengingat struktur konfigurasi saat ini, yang telah saya pilih, apakah mungkin untuk menggunakan letsencrypt dan menjalankan berbagai layanan di bawah https?

0x450
sumber
3
Saya menulis posting blog tentang topik ini: tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-downtime
Tom Busby

Jawaban:

81

Ya, Anda dapat memiliki permintaan proxy nginx ke server HTTP, dan kemudian itu sendiri menanggapi klien melalui HTTPS. Saat melakukan ini, Anda akan ingin memastikan bahwa koneksi proxy nginx <-> tidak mungkin terendus oleh siapa pun yang diharapkan sebagai penyerang Anda. Pendekatan yang cukup aman mungkin termasuk:

  • proksi ke host yang sama (seperti yang Anda lakukan)
  • proksi ke host lain di belakang firewall Anda

Proksi ke host lain di Internet publik sepertinya tidak cukup aman.

Berikut adalah petunjuk untuk mendapatkan sertifikat Let's Encrypt menggunakan server web yang sama yang Anda gunakan sebagai proxy.

Meminta sertifikat awal Anda dari Let's Encrypt

Ubah serverklausa Anda untuk memungkinkan subdirektori .well-knowndilayani dari direktori lokal, misalnya:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

http://sub.domain.com/.well-known Di sinilah server Let's Encrypt akan mencari jawaban atas tantangan yang dikeluarkannya.

Anda kemudian dapat menggunakan klien certbot untuk meminta sertifikat dari Let's Encrypt menggunakan plugin webroot (sebagai root):

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com

Kunci, sertifikat, dan rantai sertifikat Anda sekarang akan dipasang di /etc/letsencrypt/live/sub.domain.com/

Mengkonfigurasi nginx untuk menggunakan sertifikat Anda

Pertama buat klausa server baru seperti ini:

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}

Muat ulang nginx:

service nginx reload

Verifikasi bahwa HTTPS sekarang berfungsi dengan mengunjungi https://sub.domain.comdan https://www.sub.domain.comdi peramban Anda (dan peramban lain yang secara spesifik ingin Anda dukung) dan memeriksa bahwa mereka tidak melaporkan kesalahan sertifikat.

Direkomendasikan: juga tinjau raymii.org: Keamanan SSL yang kuat pada nginx dan uji konfigurasi Anda di Labs SSL .

(Disarankan) Redirect permintaan HTTP ke HTTPS

Setelah Anda mengonfirmasi bahwa situs Anda berfungsi dengan https://versi URL, alih-alih beberapa pengguna menyajikan konten tidak aman karena mereka pergi http://sub.domain.com, arahkan mereka ke versi situs HTTPS.

Ganti seluruh serverklausa port 80 Anda dengan:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}

Anda juga harus menghapus tanda komentar pada baris ini di konfigurasi port 443, sehingga browser ingat untuk tidak mencoba versi HTTP situs ini:

add_header Strict-Transport-Security "max-age=31536000";

Perpanjang sertifikat Anda secara otomatis

Anda dapat menggunakan perintah ini (sebagai root) untuk memperbarui semua sertifikat yang dikenal dengan certbot dan memuat ulang nginx menggunakan sertifikat baru (yang akan memiliki jalur yang sama dengan sertifikat yang ada):

certbot renew --renew-hook "service nginx reload"

certbot hanya akan mencoba untuk memperbarui sertifikat yang berumur lebih dari 60 hari, jadi aman (dan disarankan!) untuk menjalankan perintah ini dengan sangat teratur , dan secara otomatis jika memungkinkan. Misalnya, Anda bisa memasukkan perintah berikut /etc/crontab:

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"

Anda dapat menguji pembaruan dengan menjalankan-kering, yang akan menghubungi server staging Let's Encrypt untuk melakukan tes nyata menghubungi domain Anda, tetapi tidak akan menyimpan sertifikat yang dihasilkan:

certbot --dry-run renew

Atau Anda dapat memaksa pembaruan awal dengan:

certbot renew --force-renew --renew-hook "service nginx reload"

Catatan: Anda dapat mengeringkan lari sesering yang Anda inginkan, tetapi pembaruan nyata tunduk pada batas tingkat Mari Enkripsi .

kebingungan
sumber
Soluton Anda sepertinya tidak bekerja untuk saya. Saya pada dasarnya memiliki konfigurasi yang sama. Ini berfungsi untuk goopen.tk, tetapi tidak www.goopen.tk
Alko
3
@Alko, instruksi jawabannya sudah benar dan membahas masalah ini. Saat menggunakan certbotatau alat lain, Anda tidak bisa lupa menentukan domain Anda dalam format www dan non-www agar berfungsi.
Paulo Coghi - Reinstate Monica
Di bawah location /.well-known, Anda harus .well-knownkeluar di jalan. Gunakan alias /var/www/sub.domain.com, bukanalias /var/www/sub.domain.com/.well-known
gldraphael
1
Adakah yang bisa menjelaskan kepada saya mengapa Anda ingin menggunakan "menulis ulang ^ https: // $ host $ request_uri? Permanen;" di sini alih-alih "mengembalikan 301 https: // $ server_name $ request_uri;"
ZaxLofful
Saya menemukan bahwa saya memerlukan tanda kutip di jalur di lokasi. location '/.well-known' {. Tidak yakin apakah ini versi versi atau hanya pengaturan saya tetapi kalau-kalau ada orang lain yang macet.
Frank V
2

Ya, Anda dapat menggunakan nginxsebagai titik akhir https dan bekerja sama dengan backend melalui http. Misalnya konfigurasi saya:

server {
        server_name host;
        listen 443 ssl;
...
 location /svn/ {
            auth_ldap off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_pass http://localhost:1080/svn/;
            proxy_redirect http://localhost:1080/ https://host/;
        }
...
}

Tapi seperti yang saya tahu, dengan mengenkripsi, Anda harus mengarahkan semua subdomain saat mendapatkan sertifikat, dan jika ini merupakan masalah, maka Anda memilih url https://host/servicealih-alihhttps://service.host

fghj
sumber