Forum Discussion
How to tell nginx to use a forward proxy to reach a specific destination
- Nov 09, 2022
Seems I have also made a mistake. In setting a proxy setting for git it treats the NGINX as a forward proxy. The issue with this is NGINX is a reverse proxy. In effect it acts as an endpoint for the forward proxy you are trying to reach.
The error is due to NGINX trying to interpret a forward proxy request. So I figure we need to tell it to not do any processing on the traffic and we do that with the stream command which passes the TCP stream directly to the destination.stream { upstream web_server { # Our web server, listening for SSL traffic # Note the web server will expect traffic # at this xip.io "domain", just for our # example here server PROXYIP:PROXYPORT; } server { listen 443; proxy_pass web_server; } }
The issue with this is it intercepts ALL traffic on 443. If you dont want that then have it listen on a different port and adjust the .gitconfig to specify its proxy on the new port. You cannot tell it to match a name because at the TCP layer there is no server name.
In order to pickup the request for gitlab you need to specify the server_name to match.
server_name the-gitlab-host;
Secondly you need to specify the forward proxy IP address (x.x.x.x) and not name. Then tell NGINX to use the original host. I've included some other useful settings as well.
proxy_set_header Host $http_host;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_intercept_errors off;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://x.x.x.x:443
Now when the request arrives at NGINX it will match the server name and forward it to the forward proxy leaving the Host intact. Documentation available here - https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
Hello.
1. Your solution
I tried your solution, here is the nginx configuration.
<GITLAB-HOST> is the host of my gitlab gitlab.mycompany.com.
server {
listen 443 ssl;
server_name <GITLAB-HOST>;
ssl_certificate /etc/nginx/certs/mycert.crt;
ssl_certificate_key /etc/nginx/certs/mykey.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/mysite.access.log;
error_log /var/log/nginx/mysite.error.log debug;
location / {
proxy_set_header Host $http_host;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_intercept_errors off;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://<PROXY-IP>:<PROXY-PORT>;
}
}
I got a timeout error message when I tried git clone command from a client.
git clone https://<LOGIN>@<GITLAB-HOST>/myrepo.git
Cloning into 'myrepo'...
fatal: unable to access 'https://<LOGIN>@<GITLAB-HOST>/myrepo.git/': Failed connect to <GITLAB-HOST>:443; Connection timed out
I think it is normal to get a timeout, because the client tries to reach directly <GITLAB-HOST> without passing through nginx, and direct connections are impossible. I saw nothing in the nginx logs.
2. Second retry
I tried the following modification from your solution.
<DNS-ALIAS-NGINX-GITLAB> is an alias DNS that I created especially for clients to send git requests to nginx host.
server {
listen 443 ssl;
server_name <DNS-ALIAS-NGINX-GITLAB>;
ssl_certificate /etc/nginx/certs/mycert.crt;
ssl_certificate_key /etc/nginx/certs/mykey.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/mysite.access.log;
error_log /var/log/nginx/mysite.error.log debug;
location / {
proxy_set_header Host $http_host;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_intercept_errors off;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://<PROXY-IP>:<PROXY-PORT>;
}
}
When I retried my git clone command, I got this error :
git clone https://<LOGIN>@<DNS-ALIAS-NGINX-GITLAB>/myrepo.git
Cloning into 'myrepo'...
fatal: unable to access 'https://<LOGIN>@<DNS-ALIAS-NGINX-GITLAB>/myrepo.git/': The requested URL returned error: 502
I saw this error message in nginx logs :
2022/11/04 16:16:23 [error] 18473#18473: *1 SSL_do_handshake() failed (SSL: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol) while SSL handshaking to upstream, client: <CLIENT-IP>, server: <DNS-ALIAS-NGINX-GITLAB>, request: "GET /myrepo.git/info/refs?service=git-upload-pack HTTP/1.1", upstream: "https://<PROXY-IP>:<PROXY-PORT>/myrepo.git/info/refs?service=git-upload-pack", host: "<DNS-ALIAS-NGINX-GITLAB>"
I don't really understand the error here, but something bothers me in this solution. I never mention in nginx conf the final host, so I don't think it can work.
3. Another modification
I tried to set the Host header to the final gitlab-host. As the forward proxy and the gitlab host listens to different port number, I had to specify the final gitlab-host port in the Host header.
server {
listen 443 ssl;
server_name <DNS-ALIAS-NGINX-GITLAB>;
ssl_certificate /etc/nginx/certs/mycrt.crt;
ssl_certificate_key /etc/nginx/certs/mykey.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/mysite.access.log;
error_log /var/log/nginx/mysite.error.log debug;
location / {
proxy_set_header Host <GITLAB-HOST>:443;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_intercept_errors off;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://<PROXY-IP>:<PROXY-PORT>;
}
}
But I got the same error than in the second try (in my git command and in nginx logs)
git clone https://<LOGIN>@<DNS-ALIAS-NGINX-GITLAB>/myrepo.git
Cloning into 'myrepo'...
fatal: unable to access 'https://<LOGIN>@<DNS-ALIAS-NGINX-GITLAB>/myrepo.git/': The requested URL returned error: 502
2022/11/04 16:34:39 [error] 20677#20677: *5 SSL_do_handshake() failed (SSL: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol) while SSL handshaking to upstream, client: <CLIENT-IP>, server: <DNS-ALIAS-NGINX-GITLAB>, request: "GET /myrepo.git/info/refs?service=git-upload-pack HTTP/1.1", upstream: "https://<PROXY-IP>:<PROXY-PORT>/myrepo.git/info/refs?service=git-upload-pack", host: "<DNS-ALIAS-NGINX-GITLAB>"
May you help me to succeed, please ?
Best regards.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com