Reverse Proxy berfungsi sebagai perantara antara client dan server backend. Client hanya berkomunikasi dengan proxy, sementara proxy meneruskan request ke server tujuan dan mengembalikan respons kembali ke client. Teknik ini membantu meningkatkan keamanan, performa, serta memungkinkan load balancing.
Instalasi Nginx #
Jalankan perintah berikut untuk memasang Nginx:
sudo apt update
sudo apt install nginx -yPastikan service nginx aktif dan berjalan otomatis:
sudo systemctl enable --now nginx
sudo systemctl status nginxMenonaktifkan Virtual Host Default #
Setelah instalasi, nonaktifkan konfigurasi bawaan Nginx agar tidak terjadi konflik:
sudo unlink /etc/nginx/sites-enabled/defaultKonfigurasi Reverse Proxy #
Diagram alur reverse proxy:
flowchart TD
CLIENT["CLIENT
(Browser / Mobile App)"]
NGINX["NGINX REVERSE
PROXY"]
BE1["BACKEND SERVER 1
10.10.10.100:8090"]
BE2["BACKEND SERVER 2
10.10.10.101:8090"]
CLIENT -->|Request| NGINX
NGINX -->|Routing / SSL / Security| BE1
NGINX -->|Routing / SSL / Security| BE2
style CLIENT fill:#0d1320,stroke:#00e5a0,stroke-width:2px,color:#e8ecf4
style NGINX fill:#0d1320,stroke:#0ea5e9,stroke-width:2px,color:#e8ecf4
style BE1 fill:#0d1320,stroke:#f59e0b,stroke-width:2px,color:#e8ecf4
style BE2 fill:#0d1320,stroke:#f59e0b,stroke-width:2px,color:#e8ecf4
Buat file konfigurasi baru bernama reverse-proxy.conf:
sudo nano /etc/nginx/sites-available/reverse-proxy.confMasukkan konfigurasi berikut (contoh dengan upstream server untuk load balancing):
upstream app {
least_conn;
server 10.10.10.100:8090;
server 10.10.10.101:8090;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.com;
server_tokens off;
autoindex off;
client_max_body_size 128M;
# Gzip Compression
gzip on;
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_proxied any;
gzip_types text/plain text/css text/javascript application/json application/xml image/svg+xml;
# SSL Configuration
ssl_certificate /path/to/your/certificate.pem;
ssl_certificate_key /path/to/your/private-key.pem;
ssl_trusted_certificate /path/to/your/chain.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_prefer_server_ciphers on;
ssl_ciphers 'TLS13+AESGCM+AES256:TLS13+AESGCM+AES128:TLS13+CHACHA20:EECDH+AESGCM:EECDH+CHACHA20';
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519:P-521:P-384:P-256;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
# Security Headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer" always;
add_header Permissions-Policy "geolocation=(self), microphone=(), camera=()" always;
# Reverse Proxy Rules
location / {
proxy_pass http://app;
proxy_redirect off;
proxy_next_upstream error timeout http_500 http_503 http_429 non_idempotent;
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;
# WebSocket / Socket.IO Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
access_log off;
# Extended Timeouts
proxy_connect_timeout 900;
proxy_send_timeout 900;
proxy_read_timeout 900;
send_timeout 900;
}
# Protected Download Area
location /download {
try_files $uri @protected_download;
}
location @protected_download {
internal;
alias /var/www/html/protected/;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}Alternatif Konfigurasi Sederhana #
Konfigurasi ini cocok digunakan ketika satu domain diarahkan ke satu backend server tanpa load balancing atau rule kompleks.
flowchart TD
CLIENT["CLIENT"]
NGINX["NGINX
(Reverse Proxy)"]
Backend["BACKEND SERVER
10.10.10.10:80"]
CLIENT -->|HTTP/HTTPS| NGINX
NGINX -->|Proxy Pass| Backend
style CLIENT fill:#0d1320,stroke:#00e5a0,stroke-width:2px,color:#e8ecf4
style NGINX fill:#0d1320,stroke:#0ea5e9,stroke-width:2px,color:#e8ecf4
style Backend fill:#0d1320,stroke:#f59e0b,stroke-width:2px,color:#e8ecf4
Buat file konfigurasi:
sudo nano /etc/nginx/sites-available/example.com.confIsi dengan:
server {
server_name example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# Opsional: melihat status cache dari upstream
add_header X-Proxy-Cache $upstream_cache_status;
location ^~/ {
proxy_pass http://10.10.10.10:80;
proxy_redirect off;
# Include parameter standar proxy
include proxy_params;
# Socket.IO / WebSocket Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Buat file proxy_params:
sudo nano /etc/nginx/proxy_paramsIsi:
proxy_set_header Host $http_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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;Fungsi:
- Mengirim IP asli client ke backend
- Mengirim scheme (http/https)
- Memastikan aplikasi backend membaca Host dan Port dengan benar
Aktifkan Konfigurasi Reverse Proxy #
Buat symlink ke sites-enabled:
sudo ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/reverse-proxy.conf dengan nama file konfigurasi Anda (misal: example.com.conf).
Cek apakah konfigurasi valid:
sudo nginx -tJika output:
syntax is ok
test is successfulMaka konfigurasi sudah benar.
Reload Nginx:
sudo systemctl reload nginxReload tidak mematikan service sehingga aman untuk production.
Proxy + Cache #
1. Tambahkan Konfigurasi Cache di nginx.conf
#
Edit file nginx.conf lalu tambahkan baris berikut pada blok http { ... }:
## Real IP Forwarding ##
set_real_ip_from 127.0.0.1;
# Private IPs
set_real_ip_from 192.168.1.0/24;
set_real_ip_from 192.168.2.0/24;
# Replace with correct visitor IP
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# Proxy Cache Settings
proxy_cache_path /var/cache/nginx/dynamic levels=1:2 keys_zone=dynamic:512m max_size=4g inactive=12h use_temp_path=off;
proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=static:512m max_size=4g inactive=12h use_temp_path=off;
proxy_temp_path /var/cache/nginx/temp;
# Info
add_header nginx-cache-status $upstream_cache_status;
## DNS Resolver ##
resolver 8.8.8.8 1.1.1.1 8.8.4.4 1.0.0.1 valid=300s;
resolver_timeout 10;2. Buat File Parameter Proxy #
proxy_params_common
sudo nano /etc/nginx/proxy_params_common# General Proxy Settings
proxy_pass $PROXY_SCHEME://$PROXY_DOMAIN_OR_IP:$PROXY_TO_PORT;
proxy_hide_header Upgrade;
proxy_http_version 1.1; # Always upgrade to HTTP/1.1
proxy_set_header Accept-Encoding ""; # Optimize encoding
proxy_set_header Connection ""; # Enable keepalives
proxy_set_header Host $host;
proxy_set_header Proxy "";
proxy_set_header Referer $http_referer;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $PROXY_FORWARDED_HOST;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header CF-Connecting-IP $http_cf_connecting_ip;
proxy_set_header CF-Visitor $http_cf_visitor;
# Buffers
proxy_buffers 256 16k;
proxy_buffer_size 128k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
# Timeouts
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
send_timeout 300s;proxy_params_dynamic
sudo nano /etc/nginx/proxy_params_dynamicKonfigurasi untuk konten dinamis (HTML, CMS, dll.) dengan aturan bypass cache:
set $EXPIRES_FOR_DYNAMIC 1m;
#############################################################################################
# Allow separate cache entries for mobile devices (smartphones & tables)
set $MOBILE "";
if ($http_user_agent ~* "(iPhone|iPod|iPad|Android|Mobile|Tablet)") {
set $MOBILE "m_";
}
# CMS (& CMS extension) specific cookies (e.g. Joomla, K2 for Joomla, WordPress, WooCommerce, PrestaShop, Magento etc.)
if ($http_cookie ~* "(joomla_[a-zA-Z0-9_]+|userID|wordpress_(?!test_)[a-zA-Z0-9_]+|wp-postpass|comment_author_[a-zA-Z0-9_]+|woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_[a-zA-Z0-9]+|wordpress_logged_in_[a-zA-Z0-9]+|sid_customer_|sid_admin_|PrestaShop-[a-zA-Z0-9]+|SESS[a-zA-Z0-9]+|SSESS[a-zA-Z0-9]+|NO_CACHE|external_no_cache|adminhtml|private_content_version)") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $EXPIRES_FOR_DYNAMIC 0;
}
# Invision Power Board (IPB) v3+
if ($cookie_member_id ~ "^[1-9][0-9]*$") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $EXPIRES_FOR_DYNAMIC 0;
}
# Invision Power Board (IPB) v4+
if ($cookie_ips4_member_id ~ "^[1-9][0-9]*$") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $EXPIRES_FOR_DYNAMIC 0;
}
if ($http_cookie ~ "ips4_IPSSessionFront") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $EXPIRES_FOR_DYNAMIC 0;
}
# Admin sections & generic entry points for CMSs (incl. Joomla, WordPress, phpBB, Drupal, Craft)
if ($request_uri ~* "(/administrator|com_user|com_users|com_contact|com_mailto|/component/user|/component/users|/component/contact|/component/mailto|/installation|/wp-admin|/wp-login.php|/cart|/my-account|/checkout|/wc-api|/addons|/lost-password|\?add-to-cart=|\?wc-api=|/ucp.php|^/status\.php|^/update\.php|^/install\.php|^/apc\.php$|^/apcu\.php$|^/admin|^/admin/.*$|^/user|^/user/.*$|^/users/.*$|^/info/.*$|^/flag/.*$|^.*/ajax/.*$|^.*/ahah/.*$|^/system/files/.*$|p=admin|/actions|/login|/logout|/connect|/signin|/signup|/register)") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $EXPIRES_FOR_DYNAMIC 0;
}
# Disable caching when the "Cache-Control" header is set to "private"
if ($http_cache_control ~* "private") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $EXPIRES_FOR_DYNAMIC 0;
}
# Proxy cache settings
proxy_no_cache $CACHE_BYPASS_FOR_DYNAMIC;
proxy_cache_bypass $CACHE_BYPASS_FOR_DYNAMIC;
proxy_cache dynamic;
#proxy_cache_background_update on;
proxy_cache_key "$MOBILE$scheme$host$request_uri";
proxy_cache_lock on;
proxy_cache_methods GET HEAD;
proxy_cache_use_stale error timeout invalid_header updating http_429 http_500 http_502 http_503 http_504; # Additional options: http_403 http_404
proxy_cache_valid 200 1s;
# Ignore all headers but "Cache-Control" to determine whether to cache the upstream response or not
proxy_ignore_headers Expires Set-Cookie Vary;
# Force client-side caching for dynamic content (commented by default)
# See "ADVANCED USERS ONLY" note at the top of this file
#expires $EXPIRES_FOR_DYNAMIC;
#proxy_hide_header Cache-Control;
#proxy_hide_header Expires;
#proxy_hide_header Pragma;
#proxy_hide_header Set-Cookie;
proxy_hide_header Vary;proxy_params_static
sudo nano /etc/nginx/proxy_params_staticKonfigurasi untuk file statis (CSS, JS, gambar, font, dll.):
# Admin sections for CMSs
if ($request_uri ~* "(/administrator|/wp-admin|/wp-login.php)") {
set $CACHE_BYPASS_FOR_STATIC 1;
}
# Proxy cache settings
proxy_no_cache $CACHE_BYPASS_FOR_STATIC;
proxy_cache_bypass $CACHE_BYPASS_FOR_STATIC;
proxy_cache static;
proxy_cache_background_update on;
proxy_cache_key "$host$request_uri";
proxy_cache_lock on;
proxy_cache_methods GET HEAD;
proxy_cache_min_uses 1;
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout invalid_header updating http_429 http_500 http_502 http_503 http_504; # Additional options: http_403 http_404
proxy_cache_valid 200 10s;
# Allow rewriting HTTP headers for static assets
proxy_ignore_headers Cache-Control Expires Set-Cookie Vary;
proxy_hide_header Cache-Control;
proxy_hide_header Expires;
proxy_hide_header Pragma;
proxy_hide_header Set-Cookie;
proxy_hide_header Vary;
# Disable logging
access_log off;common_http.conf
sudo nano /etc/nginx/common_http.confKonfigurasi umum untuk semua request:
# Common definitions for HTTP content
# Initialize important variables
set $CACHE_BYPASS_FOR_DYNAMIC 0;
set $CACHE_BYPASS_FOR_STATIC 0;
set $PROXY_DOMAIN_OR_IP $host;
set $PROXY_FORWARDED_HOST $host;
set $PROXY_SCHEME $scheme;
set $SITE_URI "$host$request_uri";
# Generic query string to request a page bypassing Nginx's caching entirely for both dynamic & static content
if ($query_string ~* "nocache") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $CACHE_BYPASS_FOR_STATIC 1;
}
# Proxy requests to "localhost"
if ($host ~* "localhost") {
set $PROXY_DOMAIN_OR_IP "127.0.0.1";
}
# Disable caching for cPanel specific subdomains
if ($host ~* "^(webmail|cpanel|whm|webdisk|cpcalendars|cpcontacts)\.") {
set $CACHE_BYPASS_FOR_DYNAMIC 1;
set $CACHE_BYPASS_FOR_STATIC 1;
}
# Fix Horde webmail forwarding
if ($host ~* "^webmail\.") {
set $PROXY_FORWARDED_HOST '';
}
# Set custom rules like domain/IP exclusions or redirects here
include custom_rules;
location / {
try_files $uri $uri/ @backend;
}
location @backend {
include proxy_params_common;
# === MICRO CACHING ===
# Comment the following line to disable 1 second micro-caching for dynamic HTML content
include proxy_params_dynamic;
}
# Enable low duration browser cache for static data files (TTL is 1 min)
location ~* \.(?:csv|json|xml|rss|atom)$ {
include proxy_params_common;
include proxy_params_static;
expires 1m;
}
# Enable browser cache for CSS / JS (TTL is 30 days)
location ~* \.(?:css|js)$ {
include proxy_params_common;
include proxy_params_static;
expires 30d;
}
# Enable browser cache for images (TTL is 60 days)
location ~* \.(?:ico|jpg|jpeg|gif|png|webp)$ {
include proxy_params_common;
include proxy_params_static;
expires 60d;
}
# Enable browser cache for fonts & fix @font-face cross-domain restriction (TTL is 60 days)
location ~* \.(eot|ttf|otf|woff|woff2|svg|svgz)$ {
include proxy_params_common;
include proxy_params_static;
expires 60d;
}
# Prevent logging of favicon and robot request errors
location = /favicon.ico {
include proxy_params_common;
include proxy_params_static;
expires 60d;
log_not_found off;
}
location = /robots.txt {
include proxy_params_common;
include proxy_params_static;
expires 1d;
log_not_found off;
}
# Deny access to files like .htaccess or .htpasswd
location ~ /\.ht {
deny all;
}3. Virtual Host dengan Cache #
sudo nano /etc/nginx/conf.d/example.com.confserver {
listen 80;
listen [::]:80;
server_name example.com;
set $PROXY_TO_PORT 8080;
include common_http.conf;
}4. Custom Rules (Opsional) #
Jika ada aplikasi tambahan (misalnya Node.js di port 3000), tambahkan aturan di custom_rules:
sudo nano /etc/nginx/custom_rules# Contoh custom rule
if ($host ~ "mynodeapp.com") {
set $PROXY_SCHEME "http";
set $PROXY_TO_PORT 3000;
}5. Test Konfigurasi & Reload #
Cek konfigurasi:
sudo nginx -tReload service:
sudo systemctl reload nginxGet Original Visitor IP (Real IP) di Apache #
Saat menggunakan proxy atau reverse proxy, IP yang tercatat di access_log backend (Apache/HTTPD) biasanya adalah IP dari proxy server, bukan IP asli visitor.
Untuk mengatasinya, kita bisa menggunakan mod_remoteip agar Apache membaca header X-Forwarded-For.
1. Buat File Konfigurasi remoteip.conf
#
Buat file baru di /etc/httpd/conf.d/remoteip.conf:
sudo nano /etc/httpd/conf.d/remoteip.confTambahkan konfigurasi berikut:
<IfModule mod_remoteip.c>
RemoteIPInternalProxy XX.XX.XX.XX
RemoteIPHeader X-Forwarded-For
</IfModule>XX.XX.XX.XX dengan IP server proxy (Nginx) Anda.
2. Edit LogFormat di httpd.conf
#
Agar log menampilkan real IP visitor, ubah format log:
LogFormat "%a %l %u %t \"%r\" %>s %b" common📌 Anda juga bisa mengubah semua
LogFormatdari%hmenjadi%a.
3. Restart Apache #
Setelah konfigurasi selesai, restart service Apache:
sudo systemctl restart httpdPurge Cache Nginx #
Kadang kita perlu menghapus cache Nginx, misalnya setelah melakukan update aplikasi atau mengganti aset statis. Untuk melakukannya, Anda bisa menggunakan script berikut:
#!/usr/bin/env bash
# Hapus cache dynamic
find /var/cache/nginx/dynamic -type f -exec rm -f {} \;
# Hapus cache static
find /var/cache/nginx/static -type f -exec rm -f {} \;
# Hapus cache temp
find /var/cache/nginx/temp -type f -exec rm -f {} \;
# Restart service nginx
systemctl restart nginxSimpan script ini dengan nama, misalnya:
sudo nano /usr/local/bin/nginx-purge-cache.shKemudian beri permission agar bisa dieksekusi:
sudo chmod +x /usr/local/bin/nginx-purge-cache.shSekarang Anda dapat menghapus cache Nginx dengan mudah:
sudo nginx-purge-cache.shHardening Nginx #
1. Limit Open Connections (anti-DoS sederhana) #
Di dalam server block:
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
server {
limit_conn conn_limit_per_ip 30;
}Mencegah 1 IP membuka terlalu banyak koneksi sekaligus.
2. Block User-Agent Buruk / Bot Jahat #
if ($http_user_agent ~* (HTTrack|wget|curl|sqlmap|nmap|nikto|fimap)) {
return 403;
}3. Block Akses Langsung ke File Sensitif #
location ~* \.(env|ini|log|sql|bak)$ {
deny all;
}4. Gunakan WAF: ModSecurity + OWASP CRS #
Install:
sudo apt install libnginx-mod-security
sudo apt install modsecurity-crsAktifkan:
modsecurity on;
modsecurity_rules_file /etc/modsecurity/modsecurity.conf;Referensi: