Зачем нужен порт
IP-адрес адресует машину. Но на машине крутится десяток процессов: web,
SSH, база, мониторинг. Когда пакет прилетает на 192.168.1.50 - кому
его отдавать?
Решает порт - 16-битное число (от 0 до 65535) в TCP/UDP-заголовке.
Каждый «слушающий» процесс привязан к конкретному порту через
bind() + listen(). Когда пакет приходит на этот порт - ядро отдаёт
его тому процессу.
Пара (IP, port) = socket address - глобально уникальный адрес endpoint'а в интернете.
Категории портов
| Диапазон | Имя | Кто использует |
|---|---|---|
| 0-1023 | well-known | Стандартные сервисы (root-only на Linux) |
| 1024-49151 | registered | Зарегистрированные у IANA сервисы |
| 49152-65535 | dynamic / ephemeral | Клиентские исходящие соединения |
Известные well-known:
- 22 SSH
- 53 DNS
- 67/68 DHCP server / client
- 80 HTTP
- 123 NTP
- 443 HTTPS
- 3306 MySQL
- 5432 PostgreSQL
- 6379 Redis
Полный список - /etc/services.
Ephemeral ports - почему ты увидишь 54321 в curl'е
Когда клиент делает соединение - он не выбирает свой порт явно.
ОС берёт случайный из ephemeral-диапазона (на Linux дефолт
32768-60999, проверить можно cat /proc/sys/net/ipv4/ip_local_port_range).
Эти порты живут на время соединения. После закрытия - освобождаются (с лагом TIME_WAIT, см. tcp-states).
Это значит: если ты делаешь много исходящих соединений - порты могут кончиться. На облачном NAT-gateway'е с тысячами клиентов это реальная проблема.
Один порт - один процесс?
По сути - да. Только один процесс может bind() на конкретный
(IP, port). Иначе EADDRINUSE.
Исключения:
- SO_REUSEPORT - несколько процессов могут слушать один порт, ядро балансирует входящие коннекты между ними (как nginx/haproxy делают)
- 0.0.0.0 vs специфический IP -
bind 0.0.0.0:80иbind 1.2.3.4:80могут конфликтовать или нет, зависит от порядка bind'а
Посмотреть кто что слушает
ss -tlnp # все TCP listening сокеты + процессы
ss -ulnp # UDP
lsof -i :443 # кто на 443
netstat -tulnp # старая школа, тоже работает
Расшифровка флагов ss:
-tTCP,-uUDP-lтолько listening-nбез DNS-резолва-pпоказать процесс (нужен root для чужих)