Перейти к содержанию

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 не поддерживается в этих версиях.

См. также

GitHub

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-sniproxy.