Put vCenter 7.0 behind a reverse proxy

In a previous post, we were discussing about the necessary config to put a vCenter 6.X (HTML5) behind nginx reverse proxy.

As VMware updated the way the single sign-on works, thsi configuration was not valid anymore…

This gave me some headaches, but after looking at the local, the redirections and the failing URL, I had to modifiy it a little and add a line to the 6.X configuration.

Here is the working configuration:

server { 
   listen 443 ssl http2; 
   server_name my_internet_vcenter_fqdn; 
   ssl_certificate /etc/letsencrypt/live/my_letsencrypt_domain/fullchain.pem; 
   ssl_certificate_key /etc/letsencrypt/live/my_letsencrypt_domain/privkey.pem; 
   include /etc/letsencrypt/options-ssl-nginx.conf; 

   location / { 
      proxy_set_header Host "your_vCenter_fqdn"; 
      proxy_set_header Origin "your_vCenter_fqdn";
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_ssl_verify off; 
      proxy_pass https://your_vCenter_fqdn; 
      proxy_http_version 1.1; 
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection "upgrade"; 
      proxy_buffering off; 
      client_max_body_size 0; 
      proxy_read_timeout 36000s; 
      proxy_redirect https://your_vCenter_fqdn/ https://my_internet_vcenter_fqdn/; 
   } 

   location /websso/SAML2 { 
      sub_filter "your_vCenter_fqdn" "my_internet_vcenter_fqdn"; 
      proxy_set_header Host your_vCenter_fqdn; 
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_ssl_verify off; 
      proxy_pass https://your_vCenter_fqdn; 
      proxy_http_version 1.1; 
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection "upgrade"; 
      proxy_buffering off; 
      client_max_body_size 0; 
      proxy_read_timeout 36000s; 
      proxy_ssl_session_reuse on; 
      proxy_redirect https://your_vCenter_fqdn/ https://my_internet_vcenter_fqdn/; 
   } 
}

Hope this will help you and of course, if you have some suggestions, be my guest!
(and no: the concept of reverse-proxiing vCenter is still not debated !!!)

You may also like

27 comments

  • S Rob 27th January 2021   Reply →

    Does this still work for you with latest vcenter? It almost works for me, but get 403 on websocket connection …
    WebSocket connection to ‘wss://_MY_internet_vcenter_FQDN/ui/app-fabric/fabric’ failed: Error during WebSocket handshake: Unexpected response code: 403

    • Just a geek 5th February 2021   Reply →

      Hi,

      I just tried with very last update (build 7.0.1.00300) and it still works for mine so problem should be somewhere else.
      Do you see anything in NGINX logs? Did it worked before?

      PS: might be important: I run NGINX 1.18.0 (on a Fedora 33 server)

  • A 5th May 2021   Reply →

    Fab thank you 🙂

  • Bjorn 8th June 2021   Reply →

    Good info but I also get 403 from v-center for the webconsole. Used to work but not after upgrade to 7.0.2.00200. Not sure if it ever worked with version 7.

    Nginx log:
    request=”GET /ui/webconsole/authd?host=xxxxxxxx&port=902&cfgFile=%2Fvmfs%2Fvolumes%2F5dbac1a0-038ef105-3f82-f403435862b8%2Fxxxxx%2Fxxxxx.vmx&thumbprint=1C:B7:D6:D6:3B:F6:FA:2D:DD:12:FC:5F:2D:7E:B2:CE:AC:13:8A:43&ticket=52792b00-3d9f-9867-b269-cd1696a9879a&vmId=vm-25679&encoding=UTF-8 HTTP/1.1″ status=”403″

    On Nginx 1.16.1 since that is what CentOS 7 comes with.

    • Just a geek 2nd July 2021   Reply →

      Hi Bjorn,

      It did work before 7U2 but I also confirm that it is not working anymore. I didn’t notice it since I’m almost working 100% from home since COVID so I don’t use my reverse that much… Thanks for sharing.

      Can you post your / location configuration, so I can test it too and update the article?
      Thanks in advance! 😉

      PS: I’m running now NGINX 1.21 on CentOS 8 (with plan to migrate to Alma Linux or another)

  • Bjorn 8th June 2021   Reply →

    v-center logs this for the HTML5 remote console(websocket):

    ui-runtime – – – Request with origin:https:// and URL: https:///ui/webconsole/authd blocked!

  • Bjorn Frostberg 9th June 2021   Reply →

    I needed:

    proxy_set_header Origin “https://your_vCenter_fqdn”;

    Under / location to get html5 web-console to work. Otherwise v-center blocks it.

    • Rado 16th November 2021   Reply →

      Hey guys, it seems I have the same was:// 403 error issue with my nginx reverse proxy config.
      How were you able to fix it? I tried adding proxy_set_header Origin “https://your_vCenter_fqdn”; in my config but still getting this 403.
      Something else? Someone to post a full working config with webconsole working?

  • K 26th August 2021   Reply →

    I coped your config and put in my vcenter host name and my ngnix server name and I still get this workflow

    public.vcenter.com/ui -> internal.vcenter.com/websso/SAML2/…/… -> public.vcenter.com/ui/…/….

    I still can not get

    public.vcenter.com/ui -> public.vcenter.com/websso/SAML2/…/… -> public.vcenter.com/ui/…/….

    What would cause my SSO to still load the internal.vcenter.com hostname?

    • Just a geek 9th December 2021   Reply →

      Hi,

      I’ve recheck the config, there was a missing “proxy_set_header Origin “your_vCenter_fqdn”;” in the first block.
      The modification was mentioned by Bjorn on a previous comment but the article was not corrected.

      Please try and let me know 😉

  • Jason 27th August 2021   Reply →

    Do you know how to do the same thing in Apache2?

    • Just a geek 9th December 2021   Reply →

      Unfortunately not, I never used Apache as a reverse proxy 🙂

  • Matt 18th May 2022   Reply →

    Thanks for this! It’s a step closer in the right direction.
    I got it to work in a pod based on latest nginx but still face some issues as mentioned in earlier comments.
    – my vCenter redirects to ADFS and this redirects back to internal url (the internal URL is in the request URI sent to ADFS)
    – websocket fails to connect for the console
    – had to configure ‘listen 443 ssl’ as haproxy in ssl passthrough mode behaves really weird and mixes backends when http2 is used

    I’m on latest vcenter 7.

    Also, are you not concerned about exposing vCenter to the public internet?

    • Just a geek 25th May 2022   Reply →

      Hi,

      ADFS is probably on my wish list and you’re right, it’s probably complicated!

      For now, my vCenter is not exposed to Internet since the last 2 updates as when they wanted to correct the last big issue, they also put some vulnerable libraries back… 😒

      But my reverse proxy is behind a firewall with IPS and with also different IP filtering lists, so the risk, even if present, is reduced. 😊

      I really need to learn NGINX the deep way!!!

  • CHALON Fabien 14th October 2022   Reply →

    Hello,
    I configured my vcenter behind a nginx reverse proxy.
    It works fine with Vcenter 6.X, but not for Vcenter 7X.

    Did you find a solution on your side ?

    • Just a geek 7th November 2022   Reply →

      Hi,

      Well, not yet but I didn’t work on it. I think now I’ll will first try with vCenter 8 and figure a solution for this one! 😉

  • Vincent 23rd October 2022   Reply →

    Hello,

    I think I made it work using Apache instead of Nginx (not the purpose of your article but it may help future readers of your article).
    Tested with Apache version 2.4.51 on Alma Linux 9 :

    Listen 443

    ServerName sub.domain.com
    SSLEngine On
    SSLCertificateFile /etc/ssl/mysitename.crt
    SSLCertificateKeyFile /etc/ssl/mysitename.key
    # Protocol ‘h2’ is only supported on Apache 2.4.17 or newer.
    Protocols h2 http/1.1

    ProxyPass / http://real_vcenter_ip/
    RewriteEngine on
    RewriteCond %{HTTP:Upgrade} =websocket
    RewriteRule /(.*) wss://real_vcenter_ip/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket
    RewriteRule /(.*) http://real_vcenter_ip/$1 [P,L]

    • Vincent 23rd October 2022   Reply →
    • Just a geek 7th November 2022   Reply →

      Hi,

      Always good for the others! 😉

      At work I might have some NGINX specialists, I have to ask them someday, there is probably a solution for it.
      I can not believe NGINX is not capable to do that but it is so complex to understand every little option with interations to the others.

  • Jan Stasik 8th February 2023   Reply →

    Hello,
    I made it working on NGINX following your syntax. Thank you so much as i spent days trying to fix it. Your guide works like a charm…. Below is working config without sensitive data…anyway, vcenter is not exposed to internet but only to internal network…. I am using simple access list using apache .htpasswd where you can filter the access based on IP, otherwise it will ask for password ..sensitive data and IPs are ****** public fqdn is vsphere. and private/real fqdn is vcenter…hope it helps…
    server {
    server_name vsphere.*********.****;
    listen 443 ssl;
    server_tokens off;

    include /etc/nginx/snippets/strong-ssl.conf;

    error_log /var/log/nginx/vsphere.error;
    access_log /var/log/nginx/vsphere.access;

    satisfy any;
    allow *.*.*.*/24;
    allow *.*.*.*/24;
    allow *.*.*.*;
    deny all;

    # Basic Auth to protect the site
    auth_basic “Restricted”;
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
    proxy_set_header Host vcenter.***.***;
    proxy_set_header Origin vcenter.***.***;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_ssl_verify off;
    proxy_pass https://vcenter.***.***;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect https://vcenter.***.***/ https://vsphere.***.***/;
    }

    location /websso/SAML2 {
    sub_filter vcenter.***.** vsphere.***.**;
    proxy_set_header Host vcenter.***.**;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_ssl_verify off;
    proxy_pass https://vcenter.***.**;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_ssl_session_reuse on;
    proxy_redirect https://vcenter.***.**/ https://vsphere.***.**/;
    }

    ssl_certificate /etc/nginx/*_dd/*_bund.crt;
    ssl_certificate_key /etc/nginx/*_dd/*_dd.key;

    }

    server {
    if ($host = vsphere.***.**) {
    return 301 https://$host$request_uri;
    }

    listen 80;
    server_name vsphere.***.**;
    return 404;

    }

  • strike 10th May 2023   Reply →

    i got same err too when i open web console 403 with nginx.conf as menthioned ,
    i fix this issue with set proxy_buffering on; then i can use web console to operate ,thanks a lot

  • strike 10th May 2023   Reply →

    my vcenter version is 7.0u2

  • strike 10th May 2023   Reply →

    i got the same err too when i opened the web console it return 403 immediately with nginx.conf as menthioned
    i fix this issue with set proxy_buffering on;
    thank you guys for your support
    my vcenter version is 7.0.3;

  • Simon 16th October 2023   Reply →

    I must have read this guide a thousand times over the weekend…..i cannot get this working with vCentre 7.0.3

    My issue is that when accessing EXTERNAL.vcentre and clicking on login, I get redirected to INTERNAL.vcentre/websso/SAML2/SSO/etc

    Has any bright spark managed to get a solution?

    • Hoanguyen 28th March 2024   Reply →

      Same my issues

  • vivi_zhu 4th June 2024   Reply →

    i fix this issue with set :
    proxy_set_header Origin “https://yourvcenter.*.*.*”;

  • vivi_zhu 4th June 2024   Reply →

    It is my config
    server {
    listen 0.0.0.0:443 ssl;
    server_name vcenter.xxx.xxx;
    ssl_certificate server.crt;
    ssl_certificate_key server.key;
    ssl_session_timeout 5m;
    ssl_prefer_server_ciphers on;
    ssl_ciphers HIGH:!aNULL:!MD5:!DES:!3DES;
    client_max_body_size 10240m;
    location / {
    add_header ‘Access-Control-Allow-Origin’ ‘*’;
    add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS’;
    add_header ‘Access-Control-Allow-Headers’ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization’;
    add_header ‘Access-Control-Allow-Credentials’ ‘true’;

    # 当处理预检请求时,确保响应正确
    if ($request_method = ‘OPTIONS’) {
    add_header ‘Access-Control-Allow-Origin’ ‘*’;
    add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS’;
    add_header ‘Access-Control-Allow-Headers’ ‘DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization’;
    add_header ‘Access-Control-Allow-Credentials’ ‘true’;
    add_header ‘Access-Control-Max-Age’ 1728000;
    add_header ‘Content-Type’ ‘text/plain charset=UTF-8’;
    add_header ‘Content-Length’ 0;
    return 204;
    }
    sub_filter “vcenterlocal.xx.xx.xx” “vcenter.xxx.xxx”;
    proxy_set_header Host “vcenterlocal.xx.xx.xx”;
    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_http_version 1.1;
    proxy_set_header Origin “https://vcenterlocal.xx.xx.xx”;
    proxy_buffering off;
    proxy_ssl_verify off;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;
    proxy_pass https://vcenterlocal.xx.xx.xx;
    }
    location /ui/app-fabric/ {

    proxy_set_header Host $host;
    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_http_version 1.1;
    proxy_buffering on;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;
    proxy_pass https://vcenterlocal.xx.xx.xx;
    }

    location /websso/SAML2 {
    sub_filter “vcenterlocal.xx.xx.xx” “vcenter.xxx.xxx”;
    proxy_set_header Host “vcenterlocal.xx.xx.xx”;
    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_http_version 1.1;
    proxy_buffering on;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;
    proxy_ssl_session_reuse on;
    proxy_pass https://vcenterlocal.xx.xx.xx;
    }
    }

Leave a comment