پروکسی سرور یک سرور واسط است که تمامی درخواست ها را به مقاصد مختلف هدایت می کند. سرورهای مقصد درخواست کننده ها را به صورت مستقیم نمی بینند.

پس از دریافت یک درخواست، سرور پروکسی یک پورت به آن اختصاص می دهد و سپس درخواست را به مقصد ارسال می کند. پس از دریافت پاسخ، جواب درخواست از طریق همان اتصال قبلی به درخواست کننده ارسال می شود.

proxy server

بر خلاف پروکسی سرور، یک پروکسی معکوس در کنار وب سرورها قرار می گیرد. درخواست کننده ها تمامی وب سرورها و سرویس های پشت پروکسی معکوس را به شکل یک سرور می بینند و توانایی تفکیک آنها را از هم ندارند.

reverse proxy server

پروکسی معکوس درخواست ها را به یکی از سرورها ارسال می کند. پاسخ دریافتی به گونه ای ارسال می شود که هیچ تغییری در آن صورت نپذیرد با این اختلاف که درخواست کننده متوجه ماهیت سرور پاسخ دهنده نخواهد شد.

    موارد استفاده از پروکسی معکوس:

  • تقسیم بار

    پروکسی معکوس را می توان بعنوان یک تقسیم کننده بار در مقابل سرورها قرار داد؛ به گونه ای که حجم درخواست ها بین چندین سرور تقسیم شود. این امر باعث افزایش سرعت و قابلیت پاسخگویی و همچنین اطمینان از عدم اشغال کامل یک سرور می شود. اگر یکی از سرورها پاسخگو نباشد، بار آن بین سرورهای باقیمانده تقسیم می گردد.

  • بهبود سرعت وب

    پروکسی معکوس می تواند در خواست ها را فشرده کرده تا بار ترافیکی کاهش یابد. علاوه بر فشرده سازی برای کاهش بار می توان از قابلیت cache در پروکسی های معکوس هم استفاده نمود.

  • رمزنگاری SSL

    رمزنگاری SSL معمولا بر روی وب سرورها انجام نمی شود؛ می توان از پروکسی معکوس برای رمزنگاری تمامی درخواست ها استفاده کرد. با استفاده از این امکان، نیازی به تنظیم نمودن SSL بر روی هر سرور به صورت جداگانه نیست.

نصب NGINX

در هنگام نوشتن این پست NGINX بر روی نسخه 1.14.2قرار داشت.

    CentOS/RHEL:

  1. نصب مخزن EPEL:

    $ sudo yum install epel-release
  2. بروزرسانی مخزن:

    $ sudo yum update
  3. نصب NGINX Open Source:

    $ sudo yum install nginx
  4. اطمینان از نصب:

    $ sudo nginx -v

    Debian/Ubuntu:

  1. بروزرسانی مخزن اصلی:

    $ sudo apt-get update
  2. نصب NGINX Open Source:

    $ sudo apt-get install nginx
  3. اطمینان از نصب:

    $ sudo nginx -v

روش های دیگر نصب و همچنین دیگر سیستم عامل ها را در این لینک پیدا خواهید کرد: Installing NGINX Open Source

تنظیمات NGINX

فرض کنید بر روی سرور ۲ سرویس وب داریم. یکی با استفاده از apache بر روی پورت ۸۰۸۰؛ و دیگری یک سرویس nodejs بر روی پورت ۸۰۹۰.

URLهای سرویس اول به شکل زیر است:

http://localhost:8080/login
http://localhost:8080/home
http://localhost:8080/assets/css/home.css
http://localhost:8080/assets/js/home.js

و URLهای سرویس دوم:

http://localhost:8090/api
http://localhost:8090/api/getAll
http://localhost:8090/api/set

حال، تنظیمات NGINX را انجام می دهیم. مکان اصلی این فایل /etc/nginx/nginx.conf می باشد:

1
2
3
4
5
6
server {
    listen 80;
    listen [::]:80;

    server_name example.com; 
}

مقدار example.com را با نام دامنه خود جایگزین کنید.

سرویس اصلی را بر روی پورت ۸۰ باز کرده ایم(خط 2). حال می بایست قوانین جایگزینی URLها را بنویسیم. خط های زیر را بعد از server_name اضافه کنید.

1
2
3
4
5
6
location /app {
    proxy_pass http://localhost:8080/;
}
location /api {
    proxy_pass http://localhost:8090/api/;
}

اگر URL با /app شروع شود، درخواست به اولین سرویس ارسال می شود.

http://localhost/app/login => http://localhost:8080/login
http://localhost/app/home => http://localhost:8080/home
http://localhost/api/getAll => http://localhost:8090/api/getAll
http://localhost/app/xxxx => http://localhost:8080/xxxx
http://localhost/api/xxxx => http://localhost:8090/api/xxxx

تنظیمات پیشرفته

برنامه های بر خط هیج یک از داده های خود را cache نمی کنند،پس بهتر است در پروکسی معکوس هم این قابلیت غیرفعال شود.

1
2
3
4
location /api {
    proxy_pass http://localhost:8090/api/;
    proxy_buffering off;
}

برای اضافه کردن اطلاعات اضافی به header درخواست از نمونه کد زیر استفاده می کنیم:

1
2
3
4
5
location /app {
    proxy_pass http://localhost:8080/;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
}

با استفاده از متغیر $remote_addr می توان IP درخواست دهنده را به سرور تحویل داد.

همچنین مثل قطعه کد زیر می توان از regular expressionها در قسمت location استفاده نمود:

1
2
3
location  ~ ^/app/css/(.*)$ {
    proxy_pass   http://localhost:8080/assets/css/$1;
}
http://localhost/app/css/home.css => http://localhost:8080/assets/css/home.css

همچنین استفاده از rewrite:

1
2
3
4
location  /app/ {
    rewrite    ^/app/dashboard/(.*)$ /app/home?path=$1 break;
    proxy_pass   http://localhost:8080/;
}
http://localhost/app/dashboard/addUser => http://localhost:8080/home?path=addUser
http://localhost/app/assets/css/home.css => http://localhost:8080/assets/css/home.css

استفاده از تقسیم بار در NGINX

سرورهایی که بار بین آنها تقسیم می شود را به صورت زیر تعریف می کنیم:

1
2
3
4
5
upstream backend {
    server 10.1.0.101; 
    server 10.1.0.102;
    server 10.1.0.103;
}

حال می توان در قسمت location از این قابلیت استفاده نمود:

1
2
3
4
5
6
7
server {
    listen 80; 
 
    location / {
       proxy_pass http://backend;
    }
}

رمزنگاری SSL

ابتدا فایل های certification را به صورت زیر تعریف می کنیم:

1
2
3
4
5
http {
    ssl_certificate     /root/certs/example.com/example.com.crt;
    ssl_certificate_key /root/certs/example.com/example.com.key;
    ssl_ciphers         EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
    ssl_protocols       TLSv1.1 TLSv1.2;

حال با قطعه کد زیر SSL بر روی سرویس ها فعال می شود:

1
2
3
4
5
6
7
8
9
10
11
12
server {
    listen              203.0.113.30:443 ssl;
    listen              [2001:DB8::5]:443 ssl;
    server_name         example1.com www.example1.com;
    root                /var/www/example1.com;
}
server {
    listen              203.0.113.40:443 ssl;
    listen              [2001:DB8::6]:443 ssl;
    server_name         example2.com www.example2.com;
    root                /var/www/example2.com;
}