Docker’da Reverse Proxy ve Güvenlik: Nginx Proxy Manager ile Uygulama Koruma Rehberi
Giriş
Docker’da Reverse Proxy ve Güvenlik: Nginx Proxy Manager ile Uygulama Koruma Rehberi
Giriş
Web dünyasında bir servisi doğrudan internete sunmak, onu birçok güvenlik riskine karşı korumasız bırakmaktır. Peki, web servislerimizi doğrudan dış dünyaya açmak yerine, araya bir “Güvenlik Kapısı” koyarak trafiği kontrol altına alsak nasıl olurdu?
Bu yazıda, Docker altyapısı üzerinde çalışan bir web servisini, Nginx Proxy Manager (NPM) kullanarak nasıl bir “Reverse Proxy” katmanıyla koruma altına alacağımızı inceleyeceğiz.
Neden Reverse Proxy Kullanmalıyız?
Bu yazının temel amacı, web servisimizi internete doğrudan maruz bırakmak yerine; Reverse Proxy ve çok katmanlı güvenlik önlemleriyle koruma altına almaktır. Bu mimari sayesinde şunları gözlemliyoruz:
- Erişim Kontrolü: Kullanıcı adı ve şifre (Basic Auth) gibi katmanlarla yetkisiz kişilerin site içeriğine erişimini engelleyebiliriz.
- Trafik Şifreleme (HTTPS/TLS): Verilerin çalınmasını önlemek için şifreleme protokollerini (SSL/TLS) kullanabiliriz.
- İzlenebilirlik (Audit Logs): Tüm yapılandırma değişikliklerini saniye saniye kayıt altına alarak sistem üzerindeki hareketleri takip edebiliriz.
- IP Gizleme: Gerçek sunucu IP adresini ve port numarasını dış dünyaya kapalı tutarak saldırıyı minimize edebiliriz.
Aşağıdaki şema, bu mimarinin çalışma mantığını özetlemektedir

Portainer Üzerinde Stack Kurulumu (Adım Adım)
Sayfamda daha önce Docker’ın ve portainerin kurulumundan bahsettim oraya göz atabilirsiniz, şimdi adım adım yapılandırmaya geçelim.
Portainer’ın Stacks bölümü, birden fazla container’ın tek bir proje olarak yönetilmesini sağlar. Nginx Proxy Manager’ı bu yapı üzerinden deploy ederek hem yönetilebilirlik hem de sürdürülebilirlik kazanacağız.

Gördüğümüz boş liste henüz bir yapılandırma yapmadığımızı gösteren, sistemin başlangıç durumudur.
NPM Stack Yapılandırması (Docker Compose): Nginx Proxy Manager’ı bir “Stack” olarak kurmak için gerekli YAML kodlarını yazalım. Burada veritabanı bağımlılığını ve hangi portların (80, 81, 443) dışarı açılacağını tanımlamış olacağız. (+ Add stack)
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
# HTTP ve HTTPS portları
- '80:80'
- '443:443'
# Yönetim paneli portu
- '81:81'
volumes:
# Yapılandırma dosyaları ve SSL sertifikaları için kalıcı depolama
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
environment:
# Veritabanı yapılandırması (SQLite)
- DB_SQLITE_FILE=/data/database.sqlite
# İsteğe bağlı: Başka veritabanı türleri kullanmak istersen burayı değiştirebilirsin
networks:
- npm-network
networks:
npm-network:
external: true

Daha sonra izlememiz gereken adım ise şöyledir:

- Environment Variables: Eğer projenizde veritabanı şifreleri, API anahtarları veya uygulama ayarları gibi değişkenler varsa, bunları “Environment variables” bölümünden tanımlayabilirsiniz. Sistem, burada belirlediğiniz değişkenleri otomatik olarak bir
stack.envdosyası oluşturarak yapılandırmaya dahil eder. - Access Control: Burası yönetim güvenliği açısından oldukça kritiktir. “Enable access control” seçeneğini aktif ederek, bu stack’i kimin yönetebileceğini belirleyebiliriz.
- Administrators: Bu seçeneği seçerek, sadece yönetici yetkisine sahip kullanıcıların bu servise müdahale edebilmesini sağlıyoruz.
- Restricted: Eğer çok kullanıcılı bir ortamda çalışıyorsanız, yönetimi sadece belirli ekip üyelerine veya takımlara kısıtlayabilirsiniz.
- Deploy the stack: Tüm yapılandırmalar tamamlandığında, “Deploy the stack” butonuna basarak Nginx Proxy Manager konteynerimizi Docker üzerinde canlıya alıyoruz.
Bu adımda yönetici yetkilerini belirledik ve “Deploy” diyerek sistemi canlıya almış olacağız.
Başarılı Kurulum Teyidi: Nginx Proxy Manager stack’inin sorunsuz bir şekilde çalıştığını listede gördüğümüz aşamadır.

Demo Web Uygulamasının Kurulması: Koruma altına alacağımız hedef web sitesini tek bir “Konteyner” olarak kurduk. Bu siteye doğrudan dışarıdan erişilemez; sadece iç ağda çalışır.

- Konteyner İsmi: Sitemize
demo-webismini veriyoruz. Bu isim, ileride Reverse Proxy üzerinden yönlendirme yaparken hedefi tanımlamamız için önemlidir. - İmaj Seçimi: İmaj olarak
nginxdemos/hello:latestkullanıyoruz. Bu, sistemin çalışıp çalışmadığını test etmek için ideal bir "kurban" uygulamasıdır. - Port Eşleştirme (Port Mapping): Görselin en önemli kısımlarından biri burasıdır.
- Konteynerimizin içeride 80 portunda çalıştığını belirtiyoruz.
- Dışarıya (Host tarafına) ise 8000 portunu açıyoruz
- Neden Önemli? Bu sayede servisimiz dış dünyaya doğrudan 80 portundan değil, bizim belirlediğimiz port üzerinden bağlanacak şekilde izole edilmiş olur. Reverse Proxy’miz, gelen istekleri karşılayıp bu içerideki portlara yönlendirerek gerçek sunucu yapımızı dış dünyadan tamamen gizlemiş olacak.
“Deploy” diyerek bu konteyneri ayağa kaldırıyoruz ve artık Nginx Proxy Manager ile internete açmaya hazır hale getiriyoruz.
NPM Yönetim Paneline İlk Giriş
Nginx Proxy Manager stack’imiz başarıyla ayağa kalktığında, artık http://sunucu-ip-adresiniz:81 adresi üzerinden yönetim paneline erişebiliriz. Gördüğümüz bu ekran, "Güvenlik Kapısı" merkezi kontrol paneline ilk adımıdır.

- Yönetici Kimliği Oluşturma: Sisteme ilk kez giriş yaparken bizden bir yönetici hesabı oluşturmamızı ister. Bu, sistem yönetimi güvenliğinin başladığı kritik noktadır.
- Kimlik Doğrulama: Burada belirleyeceğimiz güçlü bir şifre, tüm proxy yönlendirmelerimizin, güvenlik kurallarımızın ve SSL sertifikalarımızın korunmasını sağlar. Buradaki bilgiler, sistemin “anahtarı” niteliğindedir; bu nedenle sadece yönetici tarafından bilinen, güçlü bir şifre kullanılması siber güvenlik ilkeleri gereğidir.
Bilgileri girdikten sonra “Save” diyerek ana yönetim paneline geçerek artık projemizin asıl “trafik polisliğini” yapacak olan yönlendirme kurallarımızı tanımlamaya başlayabiliriz.
NPM Ana Paneli: Tüm proxy yönlendirmelerini, SSL sertifikalarını ve logları takip edeceğimiz merkezi kontrol sistemidir.

Access List (Erişim Listesi) Bölümü: Sitemize sadece belirli kişilerin girebilmesi için oluşturacağımız “Güvenlik Kapısı” alanıdır.

Yeni Erişim Listesi Tanımlama: “sunumOzel” adında bir liste oluşturarak, siteye girişte kullanıcı adı ve şifre sorulmasını sağlayalım.

Kullanıcı Yetkilendirme: Giriş yapacak kişiye bir kullanıcı adı (demo) ve şifre atadık. Bu, siber güvenlikteki “Kimlik Doğrulama” (Authentication) adımıdır.
- Details (Detaylar):
- Name: Oluşturduğunuz erişim listesine verdiğiniz isimdir (bu örnekte “sunumOzel” olarak girdim).
- Satisfy Any: Eğer aktif edilirse, tanımladığınız kurallardan (örneğin kullanıcı adı/şifre veya IP kısıtlaması) herhangi birinin sağlanması erişim için yeterli olur. Kapalıysa, tüm kuralların sağlanması gerekir.
- Pass Auth to Upstream: Eğer aktif edilirse, yapılan kimlik doğrulama bilgisini (kullanıcı adı/şifre) arka plandaki (upstream) uygulamaya iletir.

- Username (Kullanıcı Adı): Buraya sisteme erişmesini istediğiniz kişilerin kullanıcı adını girersiniz (örnekte “demo” olarak belirledim).
- Password (Şifre): Belirlediğiniz kullanıcı adına karşılık gelecek şifreyi buraya girersiniz.
- Add (Ekle) Butonu: Birden fazla kullanıcı tanımlamak isterseniz, bu butona basarak yeni kullanıcı adı ve şifre satırları ekleyebilirsiniz.
- Kırmızı “X” İşareti: Yanlışlıkla eklediğiniz veya artık kullanmak istemediğiniz kullanıcı bilgilerini listeden silmenize yarar.
IP Bazlı Kısıtlama (Whitelist): Sadece belirli IP adreslerinin siteye erişebilmesi için kurallar yazılır. Bu, yetkisiz IP’lerden gelecek saldırıları doğrudan engeller.

- Sıralama Mantığı: Ekranın üst kısmında belirtildiği gibi, “allow” (izin ver) ve “deny” (reddet) komutları tanımlandıkları sırayla uygulanır.
- Kural Tanımlama:
- Allow/Deny Seçimi: Her kural için trafiğe izin mi verileceği yoksa reddedileceği açılır menüden seçilebilir.
- Hedef Belirleme: Metin kutusuna belirli bir IP adresi, bir IP bloğu (örneğin
/24ile belirtilen alt ağlar) veya IPv6 adresi girilebilir. - Add (Ekle) Butonu: Listenize yeni kurallar eklemek için kullanılır.
- Otomatik Kural: Eğer listede en az bir kural tanımlanırsa, sistem otomatik olarak en sona “deny all” (herkesi reddet) kuralını ekler. Bu, açıkça izin vermediğiniz tüm diğer trafik kaynaklarının varsayılan olarak engellenmesini sağlayan bir güvenlik önlemidir.
Hazır Erişim Listesi: Oluşturduğumuz güvenlik kuralının NPM üzerinde aktif ve kullanıma hazır olduğunu gösteren son görüntüdür.

Proxy Host Ekleme Ekranı (NPM): Bu görselde “Add Proxy Host” butonuna basmalıyız. Bu işlemle, dışarıdan gelen istekleri karşılayacak olan “Giriş Kapısını” tanımlamak ile başlayalım. Sadece bir IP adresi değil, bir domain ismi üzerinden yönlendirme yapabilmek için bu adımı gerçekleştirelim.


Alan Adı Tanımlama (Domain Names): Buraya demo-web isimini vererek ilerledim. Bu sayede sunucumuzun IP adresini bilmeyen bir kullanıcı, sadece bu ismi yazarak sitemize ulaşabilecek. Siber güvenlikte bu, gerçek IP adresini gizlemek için kullanılan bir yöntemdir.

Hedef Servis ve Port Ayarı (Forward Host/Port): Bu ekran görüntüsü çok önemli. Burada Docker içindeki demo uygulamanın konteyner ismini veya iç IP’sini ve çalıştığı portu yazalım.
- Neden? NPM bu ayar sayesinde gelen isteği nereye “paslayacağını” öğrenir. Dış dünya 80 veya 443 portuna gelir, NPM bunu içerideki kurban sitenin portuna yönlendirir.
Block Common Exploits (Ortak Saldırıları Engelleme): Proxy ayarları içinde bu butonu aktif edelim.
Neden? Nginx Proxy Manager içinde gömülü olan temel güvenlik kurallarıdır. Block Common Exploits seçeneği, yaygın kötü amaçlı istekleri filtrelemeye yardımcı olan temel Nginx güvenlik kurallarını aktif eder. Ancak bu özellik tek başına SQL Injection veya XSS’e karşı tam koruma sağlamaz; uygulama seviyesinde ek güvenlik kontrolleri gereklidir.

SSL Sertifikası Oluşturma (OpenSSL): Terminalde openssl komutunu kullanarak kendi sertifikamızı ürettiğimiz aşamadır. Siber güvenlikte buna “Self-Signed Certificate” denir. Bu işlemle, verinin kaynaktan hedefe şifreli gitmesini sağlayacak anahtar çiftini (Private & Public Key) oluşturalım, (Bu laboratuvarda eğitim amacıyla Self-Signed Certificate kullandık. Gerçek üretim ortamlarında Let’s Encrypt veya kurumsal bir Certificate Authority tarafından imzalanmış sertifikalar tercih edilmelidir.)
openssl req -x509 -newkey rsa:2048 -nodes -keyout guvenli.key -out guvenli.crt -days 30
**openssl req**: Sertifika imzalama isteği (CSR) oluşturma veya yönetme işlevini başlatır.**-x509**: Sertifikanın bir sertifika yetkilisi (CA) tarafından imzalanmak yerine, "kendinden imzalı" (self-signed) bir sertifika olacağını belirtir.**-newkey rsa:2048**: 2048 bit uzunluğunda yeni bir RSA anahtarı oluşturur (güvenlik standardı).**-nodes**: Anahtarın bir şifre (passphrase) ile korunmamasını sağlar. Bu sayede sunucu her yeniden başladığında şifre girmenize gerek kalmaz.**-keyout guvenli.key**: Oluşturulan özel anahtarınguvenli.keyismiyle kaydedilmesini sağlar.**-out guvenli.crt**: Oluşturulan sertifika dosyasınınguvenli.crtismiyle kaydedilmesini sağlar.**-days 30**: Sertifikanın geçerlilik süresini 30 gün olarak belirler.

Sertifika Detaylarının Girilmesi: Sertifika üretilirken ülke, şehir ve kurum bilgilerini tanımlayalım Özellikle “Common Name” kısmına sitemizin adını yazarak, sertifikanın hangi domain için geçerli olduğunu belirleyelim. Bu, sertifikanın kimlik kartıdır.
Benim örneğimde;
- Country Name (Ülke): TR
- State or Province Name (Eyalet/İl): Istanbul
- Locality Name (Yer/Şehir): Istanbul
- Organization Name (Kurum Adı): demo
- Organizational Unit Name (Kurum Birimi): demo
- Common Name (Alan Adı): demo-web
Sertifika ekleme: Custom Certificate ile sertifikamızı sisteme yükleyelim,

Custom Certificate Yükleme: Ürettiğimiz .crt ve .key dosyalarını Nginx Proxy Manager arayüzüne yüklemeliyiz. Bu adım, teorik olarak hazırladığımız şifreleme anahtarlarını canlı sisteme entegre ettiğimiz andır.


Proxye sertifikayı ekleme: Hosts -> Proxy Hosts ->(üç nokta) Edit
Bu işlem, web trafiğinizi HTTPS üzerinden şifreleyerek veri güvenliğini sağlar ve tarayıcıların sitenizi “güvenli değil” şeklinde işaretlemesini önler. Kısacası, oluşturduğunuz dijital kimlik kartını (sertifikayı) proxy sisteminize tanıtarak gelen isteklerin güvenli bir şekilde yönetilmesini sağlarsınız.


SSL ve Güvenlik Sıkılaştırma: Sertifikayı aktif edip “Force SSL” ve “HSTS” gibi özellikleri açtık. Bu ayarlar, kullanıcının siteye asla şifresiz bağlanmamasını sağlayarak “Ortadaki Adam” (MitM) saldırılarını engeller, demo-web gibi bir domain ismini, Docker içindeki kurban sitemizin IP ve portuna bağladık. Bu görsel, Reverse Proxy’nin “yönlendirme” görevini nasıl yaptığını teknik olarak kanıtlar.

Bu ayarların kısa özeti şöyledir:
- SSL Certificate: Siteniz için hazırladığınız dijital kimlik kartını seçer.
- Force SSL: Güvensiz HTTP bağlantılarını otomatik olarak güvenli HTTPS’e yönlendirir.
- HTTP/2 Support: Web sitesinin daha hızlı ve verimli çalışmasını sağlayan modern bir iletişim protokolünü aktif eder.
- HSTS (Enabled & Sub-domains): Tarayıcılara siteyle sadece şifreli (HTTPS) bağlantı kurulması gerektiğini emreder ve bu kuralı alt alan adlarına da yayar.
Tarayıcı Güvenlik Uyarısı (Başarı Kanıtı): HTTPS üzerinden siteye bağlandığımızda karşımıza çıkan bu ekran aslında bir başarıdır (siteye tarayıcıya “https://demo-web” yazarak eriştim). Tarayıcı, “Bu sertifika dünyaca ünlü bir otorite tarafından imzalanmamış (Self-Signed) ama bağlantı şifreli” uyarısı verir. Bu, SSL katmanının çalıştığının görsel ispatıdır.

Acsess list kısmında oluşturduğumuz kullanıcı adını ve şifreyi girerek siteyi açıyoruz


Özetle: Bu Laboratuvarda Ne Yaptık ve Neden Önemli?
Docker üzerinde çalışan bir web sitesini internetin tehlikeli dünyasına tek başına bırakmak yerine, onun önüne güçlü bir “güvenlik muhafızı” dikmiş olduk. Attığımız adımları ve siber güvenlikteki karşılıklarını çok basitçe özetlersek:
- Gizli Bir Güvenlik Tüneli Kurduk (
external: true): Web sitemizin kapılarını dış dünyaya tamamen kapattık. Nginx Proxy Manager (NPM) ile sitemizi gizli, ortak bir Docker ağına bağladık. Böylece kötü niyetli kişiler sitemizin gerçek adresini ve portunu arkadan dolaşarak bulamayacaklar. Trafik mecburen önce NPM'e uğramak zorunda. - Kapıya Kimlik Kontrolü Koyduk (Basic Auth & Whitelist): Sitemize girmek isteyen herkesin karşısına bir kullanıcı adı/şifre ekranı çıkardık ve sadece bizim güvendiğimiz IP adreslerine izin verdik. Yani yetkisiz kişilerin daha sitemizin ilk sayfasını bile görmesini engelledik.
- Verileri Şifreli Mesajlara Dönüştürdük (SSL/TLS): Kendi ürettiğimiz SSL sertifikası (Self-Signed) ve aktif ettiğimiz sıkılaştırma ayarları (Force SSL, HSTS) sayesinde, kullanıcı ile site arasındaki tüm iletişimi şifreledik. Bu sayede, araya girip paketlerimizi gizlice dinlemek isteyen (MitM) saldırganların eline sadece anlamsız karmaşık harfler geçmesini sağladık.
Siber güvenlikte hiçbir zaman %100 koruma diye bir şey yoktur; tıpkı evimizin kapısını kilitleyip, önüne alarm takıp, pencerelerine parmaklık yapmak gibi katmanlı bir savunma kurarsak hırsızların işini imkansıza yakın hale getirebiliriz. Bu çalışma, siber güvenliğin aslında ne kadar pratik ve uygulanabilir olduğunu gösteren bir örnek oldu.
메타데이터
- post_id
- e2eba2158e05
- slug
- dockerda-reverse-proxy-ve-güvenlik-nginx-proxy-manager-ile-uygulama-koruma-rehberi-e2eba2158e05
- url
- https://medium.com/@rumeysacelik_./dockerda-reverse-proxy-ve-g%C3%BCvenlik-nginx-proxy-manager-ile-uygulama-koruma-rehberi-e2eba2158e05
- canonical_url
- https://medium.com/@rumeysacelik_./dockerda-reverse-proxy-ve-g%C3%BCvenlik-nginx-proxy-manager-ile-uygulama-koruma-rehberi-e2eba2158e05
- author_url
- https://medium.com/@rumeysacelik_.
- status
- ok
- fetched_at
- 2026-06-26 21:52:29