Encounter a strange issue when using rewrite_by_lua_block to authoriacate connect request.
Dear developer,
I am using ngx_http_proxy_connect_module to proxy requests from https to http server. However, I encountered a strange issue that lacks logic and I hope you can take a deep look into it and investigate the possible reasons and solutions.
The symptom of the problem is that
- the following code is not work
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
ngx.status = ngx.HTTP_FORBIDDEN
end
}
i had hoped that i would get a 403. but what i got is good request. "CONNECT www.google.com:443 HTTP/1.1" 200 22173 "-" "curl/7.74.0" "-" 2. the following code is not work
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
ngx.var.proxy_connect_response = string.format("HTTP/1.1 403 Forbidden\\r\\nServer: openresty/%sP\\r\\n\\r\\n", ngx.var.nginx_version)
end
}
i had hoped that i would get a 403. but i got 200 without html body and hanging. 3. the following code is not work
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
ngx.say("<h1>PROXY WAS DISABLED IN THIS SITE, PLEASE DO NOT TRY!</h1>")
ngx.exit(403)
end
}
i had hoped that i would get a 403. but i got 200 without html body and not hanging.
i found some code is good: 1.
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say("<h1>PROXY WAS DISABLED IN THIS SITE, PLEASE DO NOT TRY!</h1>")
end
}
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
ngx.exit(403)
end
}
but i can not set html body for them.
I have tried to investigate this issue myself but I failed to find any clue about it. I wonder if you could provide some guidance on how to debug this issue, or if there is any configuration or parameter I should set to prevent this issue from happening again.
Thank you very much for your help in advance.
Best regards,
L. Fee
For the cases of (1.), if proxy_connect module is enabled to handle the CONNECT request, the response of CONNECT request will be generated individually by this module, skipping the nginx output header / response filter. As a result, you cannot modify the response via the nginx header/response filter module, such as ngx.status primitive of the ngx-lua-module.
However there is an exception for nginx REWRITE module including return directive or ngx.exit of the ngx-lua-module. The rewrite module can work before proxy_connect module. For example of my test case: https://github.com/chobits/ngx_http_proxy_connect_module/blob/master/t/http_proxy_connect.t#L323
if ($host = "get-default-response.com") {
return 403;
}
or return response directly in lua-nginx-module rewrite phase
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" then
ngx.exit(402)
end
}
For case (2.), pls ensure you are correctly encapsulating the HTTP response. The code you provided is incorrect and should be replaced with \r\n instead of \\r\\n.
- your orignal code
ngx.var.proxy_connect_response = string.format("HTTP/1.1 403 Forbidden\\r\\nServer: openresty/%sP\\r\\n\\r\\n", ngx.var.nginx_version)
- right code
After debugging your original code, I found that the response was invalid, see the following tcpdump log
log of my debugging with righ lua code
server {
listen 8888;
resolver 223.5.5.5;
proxy_connect;
proxy_connect_allow 443 563;
proxy_connect_connect_timeout 10s;
proxy_connect_read_timeout 100ms;
proxy_connect_send_timeout 10s;
#access_log logs/host.access.log main;
#proxy_ignore_client_abort on;
client_body_timeout 3600s;
proxy_read_timeout 10ms;
## rewrite_by_lua_block {
## if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
## ngx.var.proxy_connect_response = "HTTP/1.1 200 CE\r\n\r\n"
## ngx.status = ngx.HTTP_FORBIDDEN
## end
## }
rewrite_by_lua_block {
if ngx.var.request_method == "CONNECT" and ngx.var.http_proxy_authorization ~= "Basic XXXXXXXXXXXXXXXXX" then
ngx.var.proxy_connect_response = string.format("HTTP/1.1 403 Forbidden\r\nServer: openresty/%sP\r\n\r\n", ngx.var.nginx_version)
end
}
- testing
xc output $ curl https://baidu.com -x localhost:8888 -sv -o /dev/null
* Trying 127.0.0.1:8888...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8888 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to baidu.com:443
> CONNECT baidu.com:443 HTTP/1.1
> Host: baidu.com:443
> User-Agent: curl/7.68.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 403 Forbidden
< Server: openresty/1.22.1P
<
* Received HTTP code 403 from proxy after CONNECT
* CONNECT phase completed!
* Closing connection 0
- tcpdump log:
xc output $ sudo tcpdump -i any -n -A port 8888
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
19:30:27.261926 IP 127.0.0.1.46474 > 127.0.0.1.8888: Flags [S], seq 587633994, win 65495, options [mss 65495,sackOK,TS val 200265004 ecr 0,nop,wscale 7], length 0
E..<.B@[email protected]..........".#..J.........0.........
...,........
19:30:27.261934 IP 127.0.0.1.8888 > 127.0.0.1.46474: Flags [S.], seq 1754985367, ack 587633995, win 65483, options [mss 65495,sackOK,TS val 200265004 ecr 200265004,nop,wscale 7], length 0
E..<..@.@.<........."...h...#..K.....0.........
...,...,....
19:30:27.261942 IP 127.0.0.1.46474 > 127.0.0.1.8888: Flags [.], ack 1, win 512, options [nop,nop,TS val 200265004 ecr 200265004], length 0
E..4.C@.@..~..........".#..Kh........(.....
...,...,
19:30:27.261996 IP 127.0.0.1.46474 > 127.0.0.1.8888: Flags [P.], seq 1:111, ack 1, win 512, options [nop,nop,TS val 200265004 ecr 200265004], length 110
E....D@.@.............".#..Kh..............
...,...,CONNECT baidu.com:443 HTTP/1.1
Host: baidu.com:443
User-Agent: curl/7.68.0
Proxy-Connection: Keep-Alive
19:30:27.296154 IP 127.0.0.1.8888 > 127.0.0.1.46474: Flags [P.], seq 1:54, ack 111, win 512, options [nop,nop,TS val 200265038 ecr 200265004], length 53
E..i!.@.@..........."...h...#........].....
...N...,HTTP/1.1 403 Forbidden
Server: openresty/1.22.1P
1
And also note that if the proxy_connect module fails to resolve the proxied backend (DNS resolve), you may receive a 503 status code as a response. In such cases, the $proxy_connect_response configuration will be ignored.
To see my test for a non-existent proxied backend domain, please refer to the following.