Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can it used as a https proxy to tunnel tcp? #22

Closed
friskfly opened this issue Nov 10, 2017 · 13 comments
Closed

Can it used as a https proxy to tunnel tcp? #22

friskfly opened this issue Nov 10, 2017 · 13 comments
Assignees
Labels
document document updating or bugfix

Comments

@friskfly
Copy link

I tried in ssl server block , but not succeed

@chobits
Copy link
Owner

chobits commented Nov 11, 2017

hi, this module is used to handle CONNECT-request tunnel, this request is plain request (not over ssl). Seems that there is no client (webbrowsers / curl ) sending CONNECT request over SSL layer.

So if u want to use this module, config it in non-ssl server.

For more details of CONNECT tunnel, see: https://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_tunneling

@chobits chobits self-assigned this Nov 11, 2017
@friskfly
Copy link
Author

friskfly commented Nov 11, 2017

Chrome and Firefox has https proxy support. other web client can use nghttpx to translate http to h2 , I'm now use nghttpx as frontend server, and nginx with this module in backend . this is a workaround way. If the moudle can directly support CONNECT request over ssl , i can just use nginx 😀. see this blog https://wzyboy.im/post/1052.html

@chobits
Copy link
Owner

chobits commented Nov 23, 2017

Thanks for sharing this idea, let me look deep into it this weekend:)

@chobits
Copy link
Owner

chobits commented Nov 25, 2017

hi @friskfly , I have made connect tunnel over ssl work. I'm currenty using chrome-https-proxy-setting with ngx_http_proxy_connect_module to write this comment :)


data stream diagram:

1. create tunnel:

[SSL] + [CONNECT request] --> nginx --TCP connection --> backend

2. proxy data stream via tunnel

[SSL] + [proxied data stream ( maybe http reqeust /https request)] --> nginx -- [proxied data stream ( maybe http reqeust /https request)] --> backend


How to use ngx_http_proxy_connect_module as https proxy

ngx_http_proxy_connect_module configure:

config Nginx server to handle CONNECT tunnel over ssl in port 8443

    server {
        listen       8443 ssl;

        server_name  localhost;

        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
        ssl_certificate     /Users/xiaochen/work/nginx/cert.pem;
        ssl_certificate_key /Users/xiaochen/work/nginx/cert.key;
        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;

        resolver 8.8.8.8;

        ### connect tunnel
        proxy_connect;
        proxy_connect_allow            443 563;
        proxy_connect_connect_timeout  10s;
        proxy_connect_read_timeout     10s;
        proxy_connect_send_timeout     10s;

        location / {
            proxy_set_header Host $host;
            proxy_pass http://$host;
        }
    }

Google Chrome https proxy setting

Note that I use chrome extension SwitchyOmega to control proxy setting. Select HTTPS in protocol option.

image

Google Chrome Error: ERR_PROXY_CERTIFICATE_INVALID

The main problem, I try to resolve, is chrome reporting error: ERR_PROXY_CERTIFICATE_INVALID.
If you have the same problem, I can show how to fix.

Note that I'm using macOS Sierra(version 10.12.6) and Goolge Chrome (Version 62.0.3202.94 (Official Build) (64-bit)).

  1. use the following script to generate SSL certificate & key.
$ cat genkey.sh
#!/bin/bash

openssl req \
  -newkey rsa:2048 \
  -x509 \
  -nodes \
  -keyout cert.key \
  -new \
  -out cert.pem \
  -subj /CN=localhost \
  -reqexts SAN \
  -extensions SAN \
  -config <(cat /System/Library/OpenSSL/openssl.cnf \
       <(printf '[SAN]\nsubjectAltName=DNS:localhost')) \
  -sha256 \
  -days 3650
$ ./genkey.sh
$ ls
cert.key   cert.pem
  1. install generated certificate cert.pem as a trusted root certificate on macOS:
1 Open Keychain Access
2 Choose "System" in the "Keychains" list
3 Choose "Certificates" in the "Category" list
4 Choose "File | Import Items..."
 Browse to the file created above, "cert.pem", select it, and click "Open"
 Select your newly imported certificate in the "Certificates" list.
5. Click the "i" button, or right click on your certificate, and choose "Get Info"
 Expand the "Trust" option
 Change "When using this certificate" to "Always Trust"
 Close the dialog, and you'll be prompted for your password.

For more details, see https://stackoverflow.com/questions/7580508/getting-chrome-to-accept-self-signed-localhost-certificate.

Here is my configure screenshot:

image

@friskfly
Copy link
Author

friskfly commented Nov 25, 2017

@chobits I tried again , with listen 443 ssl is ok , but when I configure with listen 443 ssl http2; ,chrome shows tunnel failed . There maybe some problem work with http2 .

@chobits
Copy link
Owner

chobits commented Nov 25, 2017

hi @friskfly

Yes, this is known issue in my TODO-list.

This is a long term plan, I dont have time to deal with this currently.


At least three points we should pay attention to:

  1. This module only patches HTTP status line parsing function for parsing CONNECT method.
    HTTP2 module has its own parsing function, which is not patched by this module.
  2. how to notify client that this module has established tunnel (maybe return 200 establish, not sure)
  3. how to upgrade client HTTP2 connection to TCP stream tunnel (maybe upgrade one HTTP stream not the whole connection, not sure)

@friskfly
Copy link
Author

I see. Thx for your reply.

@chobits
Copy link
Owner

chobits commented Jan 31, 2018

I am closing this issue, the TODO issue for h2 is added, see #25.

@chobits chobits closed this as completed Jan 31, 2018
@chaoqing
Copy link

Hi, I am building a https proxy to block the ads working with PAC. The idea is all https://ads.domain/any/uri will be forward proxy to nginx server and it always return empty_gif or status 204. But after I configure my nginx default.conf as follow, https_proxy=my.server:8080 curl https://www.baidu.com still return the original webpage.

    server {
        listen       8080 ssl;

        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
        ssl_certificate     /my/nginx/cert.pem;
        ssl_certificate_key /myk/nginx/cert.key;
        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;

        resolver 8.8.8.8;

        ### connect tunnel
        proxy_connect;
        proxy_connect_allow            443 563;
        proxy_connect_connect_timeout  10s;
        proxy_connect_read_timeout     10s;
        proxy_connect_send_timeout     10s;

        location / {
            empty_gif;
        }
    }

Please help me with this.

@shell1986
Copy link

Hi, is it possible to transfer the real ip address of the user through the https proxy?

@tomoncle
Copy link

无法启用 ssl

  • nginx : 1.16.1
  • OS: centos7
  • nginx info:
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-compat --with-file-aio --with-http_v2_module --add-dynamic-module=/home/tomoncle/ngx_http_proxy_connect_module

正向代理配置

server {
    listen                         6443 ssl;

    ssl_protocols                  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                    AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
    ssl_certificate                /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key            /etc/nginx/ssl/nginx.key;
    ssl_session_cache              shared:SSL:10m;
    ssl_session_timeout            10m;

    resolver 114.114.114.114;

    ### connect tunnel
    proxy_connect;
    proxy_connect_allow            443 563;
    proxy_connect_connect_timeout  10s;
    proxy_connect_read_timeout     10s;
    proxy_connect_send_timeout     10s;

    location / {
        proxy_set_header           Host $host;
        proxy_pass                 http://$host;
    }
}

测试

[root@5c5b6 ~]# curl -x 127.0.0.1:6443 -v www.baidu.com
* About to connect() to proxy 127.0.0.1 port 6443 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 6443 (#0)
> GET HTTP://www.baidu.com/ HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.baidu.com
> Accept: */*
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Thu, 23 Dec 2021 01:46:48 GMT
< Content-Type: text/html; charset=utf-8,gbk
< Content-Length: 255
< Connection: close
< 
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
* Closing connection 0
[root@5c5b6 ~]# curl -x 127.0.0.1:6443 -v https://www.baidu.com
* About to connect() to proxy 127.0.0.1 port 6443 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 6443 (#0)
* Establish HTTP proxy tunnel to www.baidu.com:443
> CONNECT www.baidu.com:443 HTTP/1.1
> Host: www.baidu.com:443
> User-Agent: curl/7.29.0
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Thu, 23 Dec 2021 01:46:54 GMT
< Content-Type: text/html; charset=utf-8,gbk
< Content-Length: 255
< Connection: close
< 
* Received HTTP code 400 from proxy after CONNECT
* Connection #0 to host 127.0.0.1 left intact
curl: (56) Received HTTP code 400 from proxy after CONNECT

问题

当我关闭ssl 时(配置文件第一行删除ssl参数)代理工作正常
当我启用ssl时(如上配置)出现以上的测试问题

我看您这边配置成功了,是可以支持 客户端 -> HTTPS -> 代理服务 -> HTTP/HTTPS -> 目标服务器 ,
但是我不知道问题出在哪里,能否给出一些意见。谢谢

@patrickkon
Copy link

I have the same problem

无法启用 ssl

  • nginx : 1.16.1
  • OS: centos7
  • nginx info:
nginx version: nginx/1.16.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-compat --with-file-aio --with-http_v2_module --add-dynamic-module=/home/tomoncle/ngx_http_proxy_connect_module

正向代理配置

server {
    listen                         6443 ssl;

    ssl_protocols                  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                    AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
    ssl_certificate                /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key            /etc/nginx/ssl/nginx.key;
    ssl_session_cache              shared:SSL:10m;
    ssl_session_timeout            10m;

    resolver 114.114.114.114;

    ### connect tunnel
    proxy_connect;
    proxy_connect_allow            443 563;
    proxy_connect_connect_timeout  10s;
    proxy_connect_read_timeout     10s;
    proxy_connect_send_timeout     10s;

    location / {
        proxy_set_header           Host $host;
        proxy_pass                 http://$host;
    }
}

测试

[root@5c5b6 ~]# curl -x 127.0.0.1:6443 -v www.baidu.com
* About to connect() to proxy 127.0.0.1 port 6443 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 6443 (#0)
> GET HTTP://www.baidu.com/ HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.baidu.com
> Accept: */*
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Thu, 23 Dec 2021 01:46:48 GMT
< Content-Type: text/html; charset=utf-8,gbk
< Content-Length: 255
< Connection: close
< 
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
* Closing connection 0
[root@5c5b6 ~]# curl -x 127.0.0.1:6443 -v https://www.baidu.com
* About to connect() to proxy 127.0.0.1 port 6443 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 6443 (#0)
* Establish HTTP proxy tunnel to www.baidu.com:443
> CONNECT www.baidu.com:443 HTTP/1.1
> Host: www.baidu.com:443
> User-Agent: curl/7.29.0
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 400 Bad Request
< Server: nginx/1.16.1
< Date: Thu, 23 Dec 2021 01:46:54 GMT
< Content-Type: text/html; charset=utf-8,gbk
< Content-Length: 255
< Connection: close
< 
* Received HTTP code 400 from proxy after CONNECT
* Connection #0 to host 127.0.0.1 left intact
curl: (56) Received HTTP code 400 from proxy after CONNECT

问题

当我关闭ssl 时(配置文件第一行删除ssl参数)代理工作正常 当我启用ssl时(如上配置)出现以上的测试问题

我看您这边配置成功了,是可以支持 客户端 -> HTTPS -> 代理服务 -> HTTP/HTTPS -> 目标服务器 , 但是我不知道问题出在哪里,能否给出一些意见。谢谢

I have the same problem too. "client sent plain HTTP request to HTTPS port while reading client request headers,"

@chobits
Copy link
Owner

chobits commented Mar 6, 2023

I have the same problem

无法启用 ssl

....

问题

当我关闭ssl 时(配置文件第一行删除ssl参数)代理工作正常 当我启用ssl时(如上配置)出现以上的测试问题
我看您这边配置成功了,是可以支持 客户端 -> HTTPS -> 代理服务 -> HTTP/HTTPS -> 目标服务器 , 但是我不知道问题出在哪里,能否给出一些意见。谢谢

I have the same problem too. "client sent plain HTTP request to HTTPS port while reading client request headers,"

hi, your configuration is right, but ur constructed curl command is not right, see my latest documentation here: https://github.com/chobits/ngx_http_proxy_connect_module#example-for-curl-connect-request-in-https

image

$ curl https://nginx.org/ -sv -o/dev/null -x https://<your-nginx-ip>:<your-nginx-port> --proxy-insecure

@chobits chobits added the document document updating or bugfix label Jun 16, 2023
Repository owner locked as too heated and limited conversation to collaborators Jun 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
document document updating or bugfix
Projects
None yet
Development

No branches or pull requests

6 participants