ngx_http_proxy_connect_module icon indicating copy to clipboard operation
ngx_http_proxy_connect_module copied to clipboard

Encounter a strange issue when using rewrite_by_lua_block to authoriacate connect request.

Open lifei opened this issue 2 years ago • 3 comments

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

  1. 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

lifei avatar May 09 '23 17:05 lifei

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
        }

chobits avatar May 12 '23 10:05 chobits

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

image


After debugging your original code, I found that the response was invalid, see the following tcpdump log

image


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

chobits avatar May 12 '23 11:05 chobits

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.

image

chobits avatar May 12 '23 11:05 chobits