NGINX-DPI: Xray

Xray по сути является целым фреймворком, который поддерживает просто огромное количество различных протоколов и алгоритмов шифрования.
В этой статье рассмотрим настройку в качестве маршрутизатора, где xray будет отправлять весь трафик через vps в Германии, а трафик chatgpt через офис в Казахстане.
Инфо по установке xray тут. Документация тут.

Настройка NGINX-DPI

Тут просто указываем адрес и порт xray-router:

local proxy_addr = "127.0.0.1";
local proxy_port = 1082;

Настройка XRAY-ROUTER

Чтобы было проще читать конфиг распишу что к чему. В секции routing описываем правила по типу если domain такой-то, то отправляем трафик на такой-то сервер по тегу (outboundTag).
В секции inbounds (входящие) указываем какой адрес и порт должен слушать xray.
В секции outbounds (исходящие) указываем сервера и с помощью тегов задаем им имена по которым и обращаемся к серверам в секции routing.

{
    "log": {
        "access": "/var/log/xray/access.log",
        "error": "/var/log/xray/error.log",
        "loglevel": "debug"
    },
    "routing": {
        "domainStrategy": "AsIs",
        "domainMatcher": "hybrid",
        "rules": [
            {
                "type": "field",
                "network": "tcp",
                "protocol": [
                    "http",
                    "tls"
                ],
                "domain": [
                    "ip.me",
                    "chat.openai.com",
                    "auth0.openai.com",
                    "lawinsider.com",
                    "instagram.com"
                ],
                "outboundTag": "kz"
            },
            {
                "type": "field",
                "network": "tcp",
                "protocol": [
                    "http",
                    "tls"
                ],
                "domain": [
                    "ifconfig.me",
                    "geoip:!ru"
                ],
                "outboundTag": "de"
            },
            {
                "type": "field",
                "domain": [
                    "geoip:ru"
                ],
                "outboundTag": "direct"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "127.0.0.1",
            "port": 1082,
            "protocol": "socks",
            "settings": {
                "udp": false,
                "ip": "127.0.0.1"
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls"
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "<server_name>",
                        "port": <server_port>,
                        "users": [
                            {
                                # id генерируется командой /usr/local/bin/xray uuid
                                "id": "<id>",
                                "encryption": "none",
                                "flow": "xtls-rprx-vision"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "tls",
                "tlsSettings": {
                    "serverName": "xray",
                    "allowInsecure": true,
                    "fingerprint": "randomized"
                }
            },
            "tag": "de"
        },
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "<server_name>",
                        "port": <server_port>,
                        "users": [
                            {
                                # id генерируется командой /usr/local/bin/xray uuid
                                "id": "<id>",
                                "encryption": "none",
                                "flow": "xtls-rprx-vision"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "tls",
                "tlsSettings": {
                    "serverName": "xray",
                    "allowInsecure": true,
                    "fingerprint": "randomized"
                }
            },
            "tag": "kz"
        },
        {
            "protocol": "freedom",
            "tag": "direct"
        }
    ]
}

Замените <server_ip> и <server_port> на свои и постарайтесь на запутаться. Также замените <id> на свои в секции users (считайте это логин и пароль по которому сервер идентифицирует клиента).

НАСТРОЙКА XRAY-SERVER

Приведу конфиг только для одного сервера поскольку они отличаются только портом и id.

{
  "log": {
    "access": "/var/log/xray/access.log",
    "error": "/var/log/xray/error.log",
    "loglevel": "error"
},
    "inbounds": [
        {
            "listen": "0.0.0.0",
            "port": <server_port>,
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "<id>",
                        "flow": "xtls-rprx-vision"
                    }
                ],
                 "decryption": "none"
            },
            "streamSettings": {
                "network": "tcp",
                "security": "tls",
                "tlsSettings": {
                    "allowInsecure": true,
                    "rejectUnknownSni": false,
                    "minVersion": "1.2",
                    "certificates": [
                        {
                            "ocspStapling": 3600,
                            "certificateFile": "/etc/ssl/hysteria-server.crt",
                            "keyFile": "/etc/ssl/hysteria-server.key"
                        }
                    ]
                }
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls"
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "tag": "direct"
        },
        {
            "protocol": "blackhole",
            "tag": "block"
        }
    ],
    "policy": {
        "levels": {
            "0": {
                "handshake": 2,
                "connIdle": 120
            }
        }
    }
}

В качестве ssl сертификата использовали самоподписный сертификат, который использовался для hysteria, но если есть сертификат от letsencrypt, то так даже лучше будет.

НАСТРОЙКА NGINX

В секцию http прописываем следующие директивы:

map $proxy_protocol_addr $proxy_forwarded_elem {
    ~^[0-9.]+$        "for=$proxy_protocol_addr";
    ~^[0-9A-Fa-f:.]+$ "for=\"[$proxy_protocol_addr]\"";
    default           "for=unknown";
}

map $http_forwarded $proxy_add_forwarded {
    "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
    default "$proxy_forwarded_elem";
}

Теперь в каждом виртуальном хосте в секции server прописываем вместо listen:

listen 127.0.0.1:8001 proxy_protocol;
listen 127.0.0.1:8002 http2 proxy_protocol;
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
real_ip_recursive on;
...

Также, если ваш сайт в корне имеет редирект, то надо добавить директиву "port_in_redirect off;", чтобы порт в ссылку не дописывался при редиректе. А еще, если браузер блокирует загрузку статики с ошибкой "blocked:mixed-content", то добавьте директиву "add_header 'Content-Security-Policy' 'upgrade-insecure-requests';".

ТЕСТИРУЕМ

Прописываем в nginx-dpi ip.me и ifconfig.me.

local force_domains = {
    "ip.me",
    "ifconfig.me",
    "openai.com",
    "lawinsider.com",
    "instagram.com",
    "cloudflare.com",
    "cloudflare.net"
}

Теперь если зайти в ip.me, то определится казахский ip-адрес, а если зайти в ifconfig.me, то немецкий.
Единственное неудобство это то, что придется вести два списка доменов, но с другой стороны таких жестких блокировок как в openai не много.

Спасибо @feel за конфигурации.

UPD 09.06.23: ПРЯЧЕМ OPENVPN

Вообщем появились нехорошие новости о возможной блокировке vpn протоколов. Решили подстраховаться и спрятать трафик openvpn site to site внутри xray на примере pfsense.
Предположим, что у сервера локальный адрес a.a.a.a, а у клиента b.b.b.b. Сперва настроим сервер openvpn.

vpn->openvpn->servers->выбираем конфигурацию сервера->protocol: TCP->interface: LAN

Теперь настроим клиент.

vpn->openvpn->clients->выбираем конфигурацию клиента->protocol: TCP->interface: LAN->server host: a.a.a.a
# далее переходим в секцию custom options и прописываем следующее
socks-proxy <xray-router-ip> <xray-router-port>;
socks-proxy-retry;

Теперь настроим xray-router. Добавим в секцию rules новое правило.

{
    "type": "field",
    "network": "tcp",
    "ip": [
        "a.a.a.a"
    ],
    "outboundTag": "kz"
},

Таким образом мы говорим xray, что если в запросе присутствует ip a.a.a.a, то трафик идет в казахский офис и далее openvpn клиент подключается к серверу по локальному ip-адресу по протоколу tcp.

Показать комментарии