HEADS UP: this is still under review. Until this notice is removed, I recommend not using this.
I have a Dell R720 at an ISP. The iDRAC connection is filtered, by the ISP, and is accessible only from a small number of IP addresses.
Sure, this talks about a web proxy. It works. So does the ssh forwarding shown at the bottom of this post.
NOTE: I should start monitoring that IP addr ess to ensure it is not publicly accessible.
My goal is to configure an Nginx reverse proxy at one of those IP addresses. Access to the proxy will be via VPN only. Configuration of the VPN is outside the scope of this post.
When I first tweeted about this back in May, I asked for suggestions and ideas. In this post, I’ll elaborate more upon my use case, which was not well explained in the tweet, and show a solution I’ve implemented. I will also consider how secure is the connection to port 5900.
My use case
The server in question (the one with the iDRAC) will be at a datacenter where I have no control.
The datacenter will firewall off the iDRAC IP address and restrict access to pre-determined IP addresses.
This is iDRAC 7 with an HTML console access.
My laptop can connect to the VPN. From there, I access the Nginx proxy via my web browser.
The Nginx proxy is not accessible unless on the VPN.
The iDRAC proxy
I was able to get a basic proxy up and running. I could login, and it worked.
But the main page did not load completely.
Searching for “nginx reverse proxy dell r720 idrac 7”, I found this reddit post. The various location /*.jsesp directives got it working for me.
The virtual console
Next, opening the virtual console showed me I needed another virtual host.
This was the window just in front of the above.
That prompted me to create the second virtual host. Once in place, the virtual console worked:
The configuration
This is the configuration I first used. I’m going to split it into three different files to remove duplication. See the next section for that solution.
[dan@[redacated]:/usr/local/etc/nginx/includes] $ cat r720-02-idrac.conf server { listen [redacted]:443 ssl http2; server_name r720-02-ipmi.int.unixathome.org; access_log /var/log/nginx/r720-02-idrac-acceess.log; error_log /var/log/nginx/r720-02-idrac-error.log; location / { proxy_pass https://[IP ADDRESS OF IDRAC]; # proxy_redirect off; # 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 http; # proxy_set_header X-NginX-Proxy true; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Protocol $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass_request_headers on; proxy_set_header Connection "keep-alive"; proxy_store off; } location /userpriv.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/userpriv.jsesp; expires 1y; add_header Cache-Control "public"; } location /functions.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/functions.jsesp; expires 1y; add_header Cache-Control "public"; } location /sysSummary.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/sysSummary.jsesp; expires 1y; add_header Cache-Control "public"; } location /sensors.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/sensors.jsesp; expires 1y; add_header Cache-Control "public"; } ssl_protocols TLSv1.2 TLSv1; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-XSS-Protection "1; mode=block"; ssl_certificate /usr/local/etc/ssl/r720-02-ipmi.int.unixathome.org.fullchain.cer; ssl_certificate_key /usr/local/etc/ssl/r720-02-ipmi.int.unixathome.org.key; } server { listen [redacted]:5900 ssl http2; server_name r720-02-ipmi.int.unixathome.org; access_log /var/log/nginx/r720-02-idrac-acceess.log; error_log /var/log/nginx/r720-02-idrac-error.log; location / { proxy_pass https://[IP ADDRESS OF IDRAC]:5900; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Protocol $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass_request_headers on; proxy_set_header Connection "keep-alive"; proxy_store off; } ssl_protocols TLSv1.2 TLSv1; # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits ssl_dhparam /usr/local/etc/ssl/dhparams.pem; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-XSS-Protection "1; mode=block"; ssl_certificate /usr/local/etc/ssl/r720-02-ipmi.int.unixathome.org.fullchain.cer; ssl_certificate_key /usr/local/etc/ssl/r720-02-ipmi.int.unixathome.org.key; }
The three file solution
These are the three files I’m using. You want to use either the above or the below, not both.
[dan@[redacted]:/usr/local/etc/nginx/includes] $ cat r720-02-idrac.conf server { listen [redacted]:443 ssl http2; include /usr/local/etc/nginx/includes/r720-02-idrac.common.inc; location / { proxy_pass https://[IP ADDRESS OF IDRAC]; include /usr/local/etc/nginx/includes/r720-02-idrac.common-proxy.inc; } location /userpriv.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/userpriv.jsesp; expires 1y; add_header Cache-Control "public"; } location /functions.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/functions.jsesp; expires 1y; add_header Cache-Control "public"; } location /sysSummary.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/sysSummary.jsesp; expires 1y; add_header Cache-Control "public"; } location /sensors.jsesp { add_header Content-Type application/javascript; proxy_pass https://[IP ADDRESS OF IDRAC]/sensors.jsesp; expires 1y; add_header Cache-Control "public"; } } server { listen [redacted]:5900 ssl http2; include /usr/local/etc/nginx/includes/r720-02-idrac.common.inc; location / { proxy_pass https://[IP ADDRESS OF IDRAC]:5900; include /usr/local/etc/nginx/includes/r720-02-idrac.common-proxy.inc; } }
[dan@[redacted]:/usr/local/etc/nginx/includes] $ cat r720-02-idrac.common.inc server_name r720-02-ipmi.int.unixathome.org; access_log /var/log/nginx/r720-02-idrac-acceess.log; error_log /var/log/nginx/r720-02-idrac-error.log; ssl_protocols TLSv1.2 TLSv1; ssl_prefer_server_ciphers on; ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:DH+AESGCM:DH+AES256:RSA+AESGCM:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-XSS-Protection "1; mode=block"; ssl_certificate /usr/local/etc/ssl/r720-02-ipmi.int.unixathome.org.fullchain.cer; ssl_certificate_key /usr/local/etc/ssl/r720-02-ipmi.int.unixathome.org.key;
[dan@[redacted]:/usr/local/etc/nginx/includes] $ cat r720-02-idrac.common-proxy.inc proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Protocol $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass_request_headers on; proxy_set_header Connection "keep-alive"; proxy_store off; [dan@[redacted]:/usr/local/etc/nginx/includes] $
How secure is that port 5900?
From my web browser to the proxy port 443: https
From the proxy, to the iDRAC port 443: https
From my web browser to the proxy port 5900: https
From the proxy to the iDRAC port 5900: also https
How do I do know the traffic from the proxy to the iDRAC is protected?
I know the iDRAC on port 443 is fine, but I’ll test it anyway.
I tested it like this:
$ openssl s_client -connect [IP ADDRESS OF IDRAC]:443 CONNECTED(00000003) Can't use SSL_get_servername depth=0 C = US, ST = Texas, L = Round Rock, O = Dell Inc., OU = Remote Access Group, CN = idrac, emailAddress = support@dell.com verify error:num=18:self signed certificate verify return:1 depth=0 C = US, ST = Texas, L = Round Rock, O = Dell Inc., OU = Remote Access Group, CN = idrac, emailAddress = support@dell.com verify return:1 --- Certificate chain 0 s:C = US, ST = Texas, L = Round Rock, O = Dell Inc., OU = Remote Access Group, CN = idrac, emailAddress = support@dell.com i:C = US, ST = Texas, L = Round Rock, O = Dell Inc., OU = Remote Access Group, CN = idrac, emailAddress = support@dell.com --- Server certificate -----BEGIN CERTIFICATE----- [redacted] -----END CERTIFICATE----- subject=C = US, ST = Texas, L = Round Rock, O = Dell Inc., OU = Remote Access Group, CN = idrac, emailAddress = support@dell.com issuer=C = US, ST = Texas, L = Round Rock, O = Dell Inc., OU = Remote Access Group, CN = idrac, emailAddress = support@dell.com --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA Server Temp Key: ECDH, P-256, 256 bits --- SSL handshake has read 1701 bytes and written 421 bytes Verification error: self signed certificate --- New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: F0EF3BA3E9318EEB32557129359941BBB24E1DBE70CBB76D539827AFF396D771 Session-ID-ctx: Master-Key: [redacted] PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: 0000 - 97 b3 3b f0 38 41 ba 63-b9 ab f7 dd cf fd ad 1a ..;.8A.c........ [redacted] 00a0 - c0 bb 14 ee f3 ea a9 10-3c f7 24 62 4b cb b6 59 ........<.$bK..Y Start Time: 1626547934 Timeout : 7200 (sec) Verify return code: 18 (self signed certificate) Extended master secret: no --- DONE
And with port 5900, I say similar output. My conclusion, I'm OK with the traffic between the proxy and the iDRAC at the ISP.
ssh port forwarding
This also works:
ssh -2 -L 127.0.0.1:8443:[IP ADDRESS OF IDRAC]:443 -L127.0.0.1:5900:[IP ADDRESS OF IDRAC]:5900 myproxy.example.org
With this, you don't need the web proxy.
Deploy
I could deploy this to each of the trusted IP addresses which are allowed access. So far, it's just one location.
I'm going to ask around about this solution and look for suggestions.
Hope this helps.