diff --git a/apisix/cli/ngx_tpl.lua b/apisix/cli/ngx_tpl.lua index 6bd33368b9d9..c7988f6f7209 100644 --- a/apisix/cli/ngx_tpl.lua +++ b/apisix/cli/ngx_tpl.lua @@ -217,15 +217,48 @@ stream { require("resty.events.compat").run() } } - + {% for _, item in ipairs(stream_proxy.tcp or {}) do %} server { - {% for _, item in ipairs(stream_proxy.tcp or {}) do %} listen {*item.addr*} {% if item.tls then %} ssl {% end %} {% if enable_reuseport then %} reuseport {% end %} {% if proxy_protocol and proxy_protocol.enable_tcp_pp then %} proxy_protocol {% end %}; + + {% if tcp_enable_ssl then %} + ssl_certificate {* ssl.ssl_cert *}; + ssl_certificate_key {* ssl.ssl_cert_key *}; + + ssl_client_hello_by_lua_block { + apisix.ssl_client_hello_phase() + } + + ssl_certificate_by_lua_block { + apisix.ssl_phase() + } {% end %} - {% for _, addr in ipairs(stream_proxy.udp or {}) do %} - listen {*addr*} udp {% if enable_reuseport then %} reuseport {% end %}; + + {% if (proxy_protocol and proxy_protocol.enable_tcp_pp_to_upstream) or item.proxy_protocol then %} + proxy_protocol on; {% end %} + preread_by_lua_block { + apisix.stream_preread_phase() + } + + proxy_pass apisix_backend; + + {% if use_apisix_base then %} + set $upstream_sni "apisix_backend"; + proxy_ssl_server_name on; + proxy_ssl_name $upstream_sni; + {% end %} + + log_by_lua_block { + apisix.stream_log_phase() + } + } + {% end %} + {% for _, addr in ipairs(stream_proxy.udp or {}) do %} + server { + listen {*addr*} udp {% if enable_reuseport then %} reuseport {% end %}; + {% if tcp_enable_ssl then %} ssl_certificate {* ssl.ssl_cert *}; ssl_certificate_key {* ssl.ssl_cert_key *}; @@ -259,6 +292,7 @@ stream { apisix.stream_log_phase() } } + {% end %} } {% end %} diff --git a/docs/en/latest/stream-proxy.md b/docs/en/latest/stream-proxy.md index 1fb9ac0bb474..fbc370d49fed 100644 --- a/docs/en/latest/stream-proxy.md +++ b/docs/en/latest/stream-proxy.md @@ -241,3 +241,16 @@ curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H "X-API-KEY: $admin_ke By setting the `scheme` to `tls`, APISIX will do TLS handshake with the upstream. When the client is also speaking TLS over TCP, the SNI from the client will pass through to the upstream. Otherwise, a dummy SNI `apisix_backend` will be used. + +## Enable upstream PROXY protocol per TCP port + +APISIX can enable upstream PROXY protocol for specific ports. + +```yaml +apisix: + proxy_mode: http&stream # enable both http and stream proxies + stream_proxy: # TCP/UDP proxy + tcp: # TCP proxy address list + - addr: 9100 + proxy_protocol: true +``` \ No newline at end of file diff --git a/t/cli/test_stream_config.sh b/t/cli/test_stream_config.sh index 4eefb477eb1f..c05d2d4d02e1 100755 --- a/t/cli/test_stream_config.sh +++ b/t/cli/test_stream_config.sh @@ -109,3 +109,61 @@ if ! grep "plugin-limit-conn-stream" conf/nginx.conf > /dev/null; then fi echo "passed: enable shdict on demand" + +# Test: per-port proxy_protocol generates proxy_protocol on in the TCP server block +echo " +apisix: + proxy_mode: http&stream + stream_proxy: + tcp: + - addr: 9100 + proxy_protocol: true +" > conf/config.yaml + +make init + +if ! grep -q "proxy_protocol on" conf/nginx.conf; then + echo "failed: per-port proxy_protocol should generate 'proxy_protocol on' in nginx.conf" + exit 1 +fi + +echo "passed: per-port proxy_protocol generates proxy_protocol on" + +# Test: without per-port proxy_protocol flag, no proxy_protocol on in TCP server block +echo " +apisix: + proxy_mode: http&stream + stream_proxy: + tcp: + - addr: 9100 +" > conf/config.yaml + +make init + +if grep -q "proxy_protocol on" conf/nginx.conf; then + echo "failed: TCP port without proxy_protocol flag should not generate 'proxy_protocol on'" + exit 1 +fi + +echo "passed: TCP port without proxy_protocol flag does not generate proxy_protocol on" + +# Test: mixed ports - only flagged port gets proxy_protocol on +echo " +apisix: + proxy_mode: http&stream + stream_proxy: + tcp: + - addr: 9100 + proxy_protocol: true + - addr: 9101 +" > conf/config.yaml + +make init + +count=$(grep -c "proxy_protocol on" conf/nginx.conf) +if [ "$count" -ne 1 ]; then + echo "failed: only the flagged TCP port should generate 'proxy_protocol on', got $count occurrences" + exit 1 +fi + +echo "passed: only the flagged TCP port generates proxy_protocol on"