Как да конфигурирате Nginx да слуша на множество портове
Nginx може да слуша на множество портове едновременно, като добавя множество `listen` директиви вътре в един или повече `server` блока в конфигурацията си. Всяка `listen` директива свързва Nginx с конкретна комбинация от IP/порт, позволявайки на един сървърен екземпляр да обработва HTTP, HTTPS и трафик на потребителски приложения на различни портове, без да стартира отделни процеси.
Тази възможност е от съществено значение за среди с множество наематели, разделяне на портове за staging/production, архитектури на обратен прокси и маршрутизиране на микроуслуги — всичко от един екземпляр на VPS Хостинг.
Предварителни изисквания
Преди да продължите, потвърдете следното:
- Nginx е инсталиран и услугата е активна (`systemctl status nginx`)
- Имате `root` или `sudo` привилегии на сървъра
- Разбирате разликата между `/etc/nginx/nginx.conf` (глобална конфигурация) и `/etc/nginx/sites-available/` (блокове за конфигурация на отделни сайтове)
- Правилата на защитната стена (`ufw`, `iptables` или облачна група за сигурност) разрешават трафик на портовете, които възнамерявате да отворите
- Налични са валидни SSL сертификати при конфигуриране на HTTPS портове (самоподписани или издадени от CA)
Архитектура на конфигурацията на Nginx: Какво трябва да знаете първо
Nginx използва йерархичен модел на конфигурация: контекстът `http` съдържа един или повече `server` блока, всеки от които може да съдържа една или повече `listen` директиви. Разбирането на тази йерархия предотвратява най-честите грешки при конфигуриране.
Ключови директиви:
- `listen [address:]port [ssl] [http2] [default_server]` — свързва сървърния блок с конкретен порт и незадължителен IP
- `server_name` — съпоставя заглавката `Host` за насочване на заявките към правилния блок
- `default_server` — определя кой сървърен блок обработва заявки, които не съответстват на никой друг `server_name`
Местоположения на конфигурационните файлове по дистрибуция:
| Дистрибуция | Основна конфигурация | Конфигурации на сайтове |
|---|---|---|
| — | — | — |
| Ubuntu / Debian | `/etc/nginx/nginx.conf` | `/etc/nginx/sites-available/` |
| CentOS / RHEL / AlmaLinux | `/etc/nginx/nginx.conf` | `/etc/nginx/conf.d/` |
| Arch Linux | `/etc/nginx/nginx.conf` | `/etc/nginx/sites-available/` |
| Docker (официален образ) | `/etc/nginx/nginx.conf` | `/etc/nginx/conf.d/` |
При системи, базирани на Debian, файловете в `sites-available/` трябва да бъдат свързани символно към `sites-enabled/` за да влязат в сила:
“`bash
sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/
“`
Стъпка 1: Отворете конфигурационния файл на Nginx
За глобална промяна, засягаща всички виртуални хостове:
“`bash
sudo nano /etc/nginx/nginx.conf
“`
За конфигурация, специфична за сайт (препоръчително за production):
“`bash
sudo nano /etc/nginx/sites-available/example.conf
“`
Използването на файлове, специфични за сайта, е силно предпочитано. То изолира промените, опростява връщането назад и предотвратява единична грешка в конфигурацията да срине всички хоствани услуги.
Стъпка 2: Конфигурирайте множество listen директиви в един сървърен блок
Най-простата настройка с множество портове свързва един сървърен блок с няколко порта. Nginx ще прилага идентична логика за маршрутизиране независимо от това през кой порт се е свързал клиентът.
“`nginx
server {
listen 80;
listen 8080;
server_name example.com;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example_access.log;
error_log /var/log/nginx/example_error.log warn;
}
“`
Какво прави това:
- `listen 80;` — приема стандартен HTTP трафик
- `listen 8080;` — приема трафик на алтернативния HTTP порт (обичайно за среди за разработка, вътрешни API или проверки за работоспособност на балансьори на натоварване)
- И двата порта обслужват идентично съдържание от `/var/www/html`
Краен случай — свързване с конкретен IP адрес: На сървър с множество мрежови интерфейси (например публичен IP и частен LAN IP), можете да ограничите кой интерфейс слуша Nginx:
“`nginx
listen 192.168.1.10:8080;
listen 0.0.0.0:80;
“`
Това е от критично значение в конфигурации на сървъри с множество домашни мрежи, за да се предотврати непреднамерено публично излагане на вътрешни услуги.
Стъпка 3: Конфигурирайте HTTPS на множество портове
HTTPS изисква параметъра `ssl` в директивата `listen` и валидни пътища до сертификат/ключ. Следният пример свързва HTTPS към стандартния порт 443 и персонализирания порт 8443:
“`nginx
server {
listen 443 ssl;
listen 8443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
Modern TLS hardening
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
“`
Защо порт 8443 се използва често:
- Позволява HTTPS трафик в среди, където порт 443 е блокиран от upstream защитни стени
- Използва се при разработка/staging за стартиране на защитен сървър без конфликт с production услуга на порт 443
- Изисква се от някои приложни рамки (Tomcat, Node.js прокси), които излагат HTTPS на нестандартни портове
Критичен проблем: Пропускането на `ssl_protocols` и `ssl_ciphers` оставя Nginx да използва потенциално слаби настройки по подразбиране. Винаги дефинирайте изрично TLS параметрите, особено на сървъри, обработващи чувствителни данни. Ако имате нужда от доверен сертификат вместо самоподписан, SSL Сертификати от признат CA премахват предупрежденията на браузъра и отговарят на съвременните изисквания за HSTS.
Стъпка 4: Обслужвайте различно съдържание на различни портове
Когато портовете трябва да обслужват различни приложения — например публичен уебсайт на порт 80 и вътрешен административен панел на порт 8080 — използвайте отделни `server` блока:
“`nginx
server {
listen 80;
server_name example.com;
root /var/www/public;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 8080;
server_name example.com;
root /var/www/admin;
index index.html;
Restrict admin panel to internal network only
location / {
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
try_files $uri $uri/ =404;
}
}
“`
Реални случаи на употреба за разделяне на съдържание по портове:
- Порт 80/443: Публично достъпен уебсайт
- Порт 8080: Вътрешен REST API или крайна точка на микроуслуга
- Порт 8443: Защитено административно табло, ограничено чрез списък с разрешени IP адреси
- Порт 9000: Крайна точка за метрики за Prometheus scraping (никога не се излага публично)
- Порт 3000/5000: Обратен прокси към приложение на Node.js или Python
Стъпка 5: Използване на Nginx като обратен прокси на множество портове
Обичаен production модел е използването на Nginx за проксиране на различни портове към различни backend сървъри на приложения:
“`nginx
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 8080;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
“`
Този модел е гръбнакът на контейнеризираните разгръщания на Dedicated сървър, където множество Docker контейнери работят на различни вътрешни портове и Nginx действа като единствена външна входна точка.
Стъпка 6: Валидирайте конфигурацията
Никога не рестартирайте Nginx, без първо да тествате синтаксиса на конфигурацията. Синтактична грешка ще причини неуспех при презареждане на услугата, сривайки всички хоствани сайтове.
“`bash
sudo nginx -t
“`
Очакван изход при успех:
“`
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
“`
Ако се появят грешки, изходът ще посочи файла и номера на реда. Отстранете всички докладвани проблеми преди да продължите.
За презареждане без прекъсване (предпочитано пред пълно рестартиране в production):
“`bash
sudo systemctl reload nginx
“`
Пълното рестартиране е необходимо само при промяна на `worker_processes`, `user` или други директиви на ниво главен процес:
“`bash
sudo systemctl restart nginx
“`
Стъпка 7: Проверете дали Nginx слуша на правилните портове
След прилагане на конфигурацията, потвърдете, че Nginx се е свързал с очакваните портове, използвайки `ss` (предпочитано пред остарялото `netstat`):
“`bash
sudo ss -tlnp | grep nginx
“`
Примерен изход:
“`
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
LISTEN 0 511 0.0.0.0:8080 0.0.0.0:* users:(("nginx",pid=1234,fd=7))
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1234,fd=8))
LISTEN 0 511 0.0.0.0:8443 0.0.0.0:* users:(("nginx",pid=1234,fd=9))
“`
Ако даден порт не се появява, проверете:
- Синтаксиса на директивата `listen` в конфигурационния файл
- Дали друг процес вече заема този порт: `sudo ss -tlnp | grep :8080`
- Дали `nginx -t` е преминал без грешки
- SELinux или AppArmor политики, които може да блокират свързването с нестандартни портове
Тестване с curl от командния ред (по-надеждно от браузър за отстраняване на грешки):
“`bash
curl -I http://example.com
curl -I http://example.com:8080
curl -Ik https://example.com
curl -Ik https://example.com:8443
“`
Флагът `-I` извлича само заглавките. Отговор `200 OK` или `301 Moved Permanently` потвърждава, че портът е активен и Nginx отговаря правилно.
Стъпка 8: Отворете портовете на защитната стена
Слушането на порт в Nginx е недостатъчно, ако защитната стена на хоста блокира входящите връзки. Уверете се, че портовете са разрешени:
UFW (Ubuntu/Debian):
“`bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8080/tcp
sudo ufw allow 8443/tcp
sudo ufw reload
“`
firewalld (CentOS/RHEL/AlmaLinux):
“`bash
sudo firewall-cmd –permanent –add-port=8080/tcp
sudo firewall-cmd –permanent –add-port=8443/tcp
sudo firewall-cmd –reload
“`
iptables (директно):
“`bash
sudo iptables -A INPUT -p tcp –dport 8080 -j ACCEPT
sudo iptables -A INPUT -p tcp –dport 8443 -j ACCEPT
“`
При облачна инфраструктура (AWS EC2, DigitalOcean, Hetzner), трябва също да актуализирате групата за сигурност или правилата на облачната защитна стена на ниво доставчик — промените на защитната стена на ниво хост сами по себе си не са достатъчни.
Сравнение: Конфигурации на Nginx с един порт срещу множество портове
| Функция | Един порт | Множество портове (същият блок) | Множество портове (отделни блокове) |
|---|---|---|---|
| — | — | — | — |
| Сложност на конфигурацията | Ниска | Ниска | Средна |
| Изолация на съдържанието | Няма | Няма | Пълна |
| Контрол на достъпа по порт | Неприложимо | Невъзможно | Напълно поддържано |
| Случай на употреба | Прости уебсайтове | Dev/staging огледала | Микроуслуги, административни панели |
| Обратен прокси по порт | Един upstream | Един upstream | Независими upstream |
| SSL терминиране | По блок | Споделен сертификат | Независими сертификати по блок |
| Разделяне на логовете | Един лог | Един лог | Лог файлове по порт |
Чести проблеми и как да ги избегнете
Конфликт на портове с съществуващи услуги: Порт 80 може вече да се използва от Apache. Стартирайте `sudo ss -tlnp | grep :80` преди конфигурирането. Спрете конфликтните услуги или ги преконфигурирайте да използват различни портове.
Конфликти на `default_server`: Ако множество сървърни блока пропуснат `default_server` или множество блока го заявят за същия порт, Nginx ще използва първия блок по ред на файловете. Бъдете изрични:
“`nginx
listen 80 default_server;
“`
IPv6 не е покрит: Добавянето на `listen 80;` свързва само с IPv4. За сървъри с двоен стек, добавете:
“`nginx
listen [::]:80;
listen [::]:8080;
“`
SELinux блокира нестандартни портове: На RHEL/CentOS с принудително прилагане на SELinux, Nginx не може да се свърже с портове, които не са в неговата политика, без изрично разрешение:
“`bash
sudo semanage port -a -t http_port_t -p tcp 8080
sudo semanage port -a -t http_port_t -p tcp 8443
“`
Забравяне за презареждане след промени: Редакциите на конфигурацията нямат ефект, докато Nginx не се презареди. Автоматизирайте това в CI/CD тръбопроводи с стъпка `nginx -t && systemctl reload nginx` след разгръщане.
Практическа матрица за вземане на решения
Използвайте този контролен списък, за да определите правилния модел на конфигурация с множество портове за вашия сценарий:
- Едно и също съдържание, множество портове — Използвайте множество `listen` директиви в един `server` блок
- Различно съдържание по порт — Използвайте отделни `server` блока с различни `root` директории
- Различни backend приложения по порт — Използвайте отделни `server` блока с `proxy_pass` сочещи към различни upstream адреси
- Защита на нестандартен порт — Добавете `ssl` към директивата `listen` и посочете пътищата до сертификата; уверете се, че SAN на сертификата покрива домейна
- Ограничаване на порт до вътрешен трафик — Добавете `allow`/`deny` директиви или свържете `listen` само с частен IP
- Работа на VPS с cPanel — Проверете дали вградената конфигурация на Apache/Nginx на cPanel не конфликтира; използвайте „Include Editor” на cPanel или специална директория за допълнителни конфигурации на Nginx
- Управление на множество опции за контролен панел — Прегледайте наличните VPS Контролни панели, за да намерите такъв, който предоставя управление на портовете на Nginx чрез GUI
Често задавани въпроси
Може ли Nginx да слуша на един и същи порт в множество сървърни блока?
Да. Множество `server` блока могат да споделят един и същи порт. Nginx разграничава между тях, използвайки директивата `server_name`, която съпоставя HTTP заглавката `Host`. Ако никой `server_name` не съответства, блокът `default_server` обработва заявката.
Влияе ли добавянето на повече listen портове на производителността на Nginx?
Натоварването е пренебрежимо малко. Всяка `listen` директива добавя файлов дескриптор към главния процес на Nginx. Практическото ограничение е таванът на отворените файлови дескриптори на системата (`ulimit -n`), а не броят на портовете. За разгръщания с висок трафик, настройте `worker_rlimit_nofile` и `worker_connections` в `nginx.conf`.
Как да пренасоча целия трафик от порт 8080 към порт 80?
Използвайте специален сървърен блок с директива `return`:
“`nginx
server {
listen 8080;
server_name example.com;
return 301 http://example.com$request_uri;
}
“`
Защо Nginx не слуша на порт, въпреки че конфигурацията изглежда правилна?
Четирите най-чести причини са: (1) конфигурацията не е презаредена след редактиране, (2) друг процес вече е свързан с този порт, (3) правило на защитната стена блокира порта, или (4) SELinux/AppArmor предотвратява свързването. Работете систематично през всяка причина, използвайки `ss -tlnp`, `nginx -t` и команди за статус на защитната стена.
Мога ли да използвам различни SSL сертификати за различни HTTPS портове на един и същи домейн?
Да. Всеки `server` блок има свои собствени `ssl_certificate` и `ssl_certificate_key` директиви. Два сървърни блока могат да слушат на портове 443 и 8443 съответно и да препращат към напълно различни файлове на сертификати, дори за един и същи `server_name`. Това е полезно при ротиране на сертификати или при едновременно използване на стар и нов сертификат по време на преходен период.
