sniproxy: SNI Proxy на основе stream-lua-nginx-module
Установка
Если вы еще не подписались на RPM репозиторий, зарегистрируйтесь. После этого вы можете продолжить с следующими шагами.
CentOS/RHEL 7 или Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-sniproxy
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-sniproxy
Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что установлен nginx-module-lua.
Этот документ описывает lua-resty-sniproxy v0.22, выпущенную 31 августа 2020 года.
Эта библиотека является SNI прокси, написанной на Lua. Часть парсинга TLS переписана из dlundquist/sniproxy.
Обратите внимание, что требуется модуль nginx stream и ngx_stream_lua_module.
Тестировалось на Openresty >= 1.9.15.1.
Синопсис
stream {
init_by_lua_block {
local sni = require("resty.sniproxy")
sni.rules = {
{"www.google.com", "www.google.com", 443},
{"www.facebook.com", "9.8.7.6", 443},
{"api.twitter.com", "1.2.3.4"},
{".+.twitter.com", nil, 443},
-- чтобы активировать это правило, вы должны использовать проксирование на Lua
-- {"some.service.svc", "unix:/var/run/nginx-proxy-proto.sock", nil, sni.SNI_PROXY_PROTOCOL_UPSTREAM},
-- {"some2.service.svc", "unix:/var/run/nginx-proxy-proto.sock", nil,
-- sni.SNI_PROXY_PROTOCOL_UPSTREAM + sni.SNI_PROXY_PROTOCOL},
{".", "unix:/var/run/nginx-default.sock"}
}
}
# для OpenResty >= 1.13.6.1, нативное проксирование Nginx
lua_add_variable $sniproxy_upstream;
server {
error_log /var/log/nginx/sniproxy-error.log error;
listen 443;
resolver 8.8.8.8;
prepread_by_lua_block {
local sni = require("resty.sniproxy")
local sp = sni:new()
sp:preread_by()
}
proxy_pass $sniproxy_upstream;
}
# для OpenResty < 1.13.6.1 или если настроены `flags`, проксирование на Lua
server {
error_log /var/log/nginx/sniproxy-error.log error;
listen 443;
resolver 8.8.8.8;
content_by_lua_block {
local sni = require("resty.sniproxy")
local sp = sni:new()
sp:content_by()
}
}
}
Таблица массива Lua sni_rules должна быть определена в директиве init_worker_by_lua_block.
Первое значение может быть либо полным именем хоста, либо регулярным выражением. Используйте . для имени хоста по умолчанию. Если ни одна запись не совпадает, соединение будет закрыто.
Второе и третье значения — это имя целевого хоста и порт. Хост может быть DNS-именем, IP-адресом или путем к сокету UNIX. Если хост не определен или установлен в nil, будет использоваться server_name в SNI. Если порт не определен или установлен в nil, будет использоваться 443.
Четвертое значение — это флаги для использования. Доступные флаги:
sni.SNI_PROXY_PROTOCOL -- использовать адрес клиента, полученный от протокола прокси, для отправки на upstream
sni.SNI_PROXY_PROTOCOL_UPSTREAM -- отправить рукопожатие протокола прокси v1 на upstream
Чтобы использовать флаги, сервер должен быть настроен для Lua land proxying (см. пример выше).
Правила применяются с приоритетом в порядке их появления в таблице. В приведенном выше примере api.twitter.com будет соответствовать третьему правилу api.twitter.com, а не четвертому .+.twitter.com.
Если версия протокола меньше TLSv1 (например, SSLv3, SSLv2), соединение будет закрыто, поскольку расширение SNI не поддерживается в этих версиях.
См. также
- модуль ngx_stream_lua_module: https://github.com/openresty/stream-lua-nginx-module
- dlundquist/sniproxy
- ngx_stream_ssl_preread_module доступен с Nginx 1.11.5 как альтернатива этому модулю.
GitHub
Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-sniproxy.