Most part of this an update of the article of Julian Pawlowski “Geeking out with HAproxy on pfSense” from 2015. So my purpose was to used it on the latest pfsense release 2.5.2. The latest at this moment.
All the captures are from me and can be a little bit different from the original text. Australia having recently become the last American aquisition. Thanks to the fella from down under.
I would like to share my experience on how to transform your pfSense appliance into a layer4 router for sharing all the encrypted traffic we have on port 443 with SSH and OpenVPN traffic.
SSLlabs.com will even give you an A+ for this configuration if you follow it closely.
For SSH, this will not only give you enhanced security and encryption but also a whole lot more flexibility for secure remote access to servers in your corporate network. It will even allow you to bypass a lot of corporate proxy servers (as long as there is no content inspection enabled for HTTPS traffic) and is a real alternative instead of using HTTP CONNECT method (which can easily be blocked).
This solution could even be more blown up to fulfill enterprise level requirements, e.g. granular role-based user authentication. However, this will not be our main topic in this article but will be referenced from time to time.
I know there is this shiny litte tool SSLH out there but this solution is much more flexible due to the power of HAproxy.
All in all, this is what we are going to share via port 443 on a single IP:
normal HTTPS traffic (acting as normal reverse proxy for securing web traffic)
Backend with reverse proxy (traefik). TCP flows
backend without any reverse proxy. HTTPS flows
normal HTTPS traffic with X509 user certificate authentication
OpenVPN dial-in traffic
TLS-tunneled SSH traffic including X509 user certificate authentication (SSLH Gateway)
The WAN_443_TCP frontend and the different parts necessary for its operation, are useful when there is a loadbalancer on the target server.
In order to test Traefik on Docker servers or to use some project like Cloudbox, I therefore added this functionality. In these cases I don’t want to modify Traefik or nginx conf files to use a proxy, each time a new version of the project come out, modifications needs to been done again and again.
On the graph below, the WIN_443_TCP is marked as using a certificate from LetsEncrypt, IT’s not for making some SSL offloading for the destination server. It’s not needed as we use TCP flow.
Be carefull, this article is still in progress.
%%{init: {"flowchart": {"htmlLabels": false}} }%%
flowchart LR
A ---> L
A ---> M
A ---> N
A ---> O
B --->|80 redirect scheme https code 301| W
L ---> T
T ---->|2043| P
M -.-> U
N -.-> V
P ---->|fa:fa-globe-europe | X
P ---->|fa:fa-globe-europe | Y
P ---->|fa:fa-globe-europe | Z
V -. 2022 .-> Q
Q -. fa:fa-terminal .-> X
Q -. fa:fa-terminal .-> Y
Q -. fa:fa-terminal .-> Z
R ---->|fa:fa-user-check| X
R ---->|fa:fa-user-check| Y
R ---->|fa:fa-user-check| Z
U -. 2044 .-> R
L --->|*.example.com from| F
N ---->|ssh.example.com| E
O --->|1194| C
O --->|vpn.example.com| D
M --->|HTTPS auth certificat check| D
A ----> H
H ----> I
H ---->|*.example.com from| F
I -. 2045 .-> J
J ---->|fa:fa-filter| X
J ---->|fa:fa-filter| Y
J ---->|fa:fa-filter| Z
subgraph ff[Frontend]
A([fa:fa-shield-alt WAN_443 Port 443 Sharing])
B([WAN_HTTP])
end
subgraph sb1[Shared Frontend]
direction TB
L{{fa:fa-globe-europe WAN_443_HTTPS}}
M{{fa:fa-user-check WAN_443_HTTP_auth}}
N{{fa:fa-terminal WAN_443_SSLH}}
O{{WAN_443_OpenVPN}}
H{{fa:fa-filter WAN_443_TCP}}
end
C[/fa:fa-fingerprint OpenVPN Daemon/]
subgraph sb2[2nd level frontend]
P{{fa:fa-globe-europe WAN_HTTPS redirect with ACL}}
Q{{fa:fa-terminal WAN_SSLH redirect with ACL}}
R{{fa:fa-user-check WAN_HTTPS_auth redirect with ACL}}
J{{fa:fa-filter WAN_TCP redirect with ACL}}
end
subgraph bk1[Specials backend]
T[fa:fa-globe-europe WAN_HTTPS on 2043]
U[fa:fa-user-check WAN_HTTPS_auth on 2044]
V[fa:fa-terminal WAN_SSLH on 2022]
I{{fa:fa-filter WAN_TCP on 2045}}
W[ssl_redirect]
end
subgraph bk2[backend]
X[fa:fa-server server_01]
Y[fa:fa-server server_02]
Z[fa:fa-server server_03]
G[fa:fa-server none]
end
subgraph cr1[certificates Authorities]
D(Acmi VPN Remote Access)
F("Let's Encrypt")
E(Acmi SSLH Gateway)
end
linkStyle 4 stroke:red,stroke-width:2px,color:red;
linkStyle 1,7,16,17,18,19 stroke:blue,stroke-width:2px,color:blue,stroke-dasharray: 5 5;
linkStyle 2,8,12,13,14,15 stroke:green,stroke-width:2px,color:green,stroke-dasharray: 5 5;
linkStyle 0,5,6,9,10,11 stroke:orange,stroke-width:2px,color:orange,stroke-dasharray: 5 5;
linkStyle 25,26,28,29,30,31 stroke:purple,stroke-width:2px,color:purple,stroke-dasharray: 5 5;
linkStyle 20 stroke:orange,stroke-width:2px,color:orange;
linkStyle 21 stroke:green,stroke-width:2px,color:green;
linkStyle 24 stroke:blue,stroke-width:2px,color:blue;
linkStyle 27 stroke:purple,stroke-width:2px,color:purple;
Creating internal Certificate Authorities and certificates
We are going to need 2 separate CA’s which we will be creating in the Cert Manager right now. I recommend using the following settings:
Creation of the first certificate autority for OpenVPN
Each user who needs to be authorized using OpenVPN, HTTPS-auth secured backends or our SSLH gateway will need to have user certificates being created by our internal CA’s.
For OpenVPN and HTTP-auth users, we will create just one single certificate. We will just use the pfSense internal users for this example, you may extend this to more complex setups on your own.
Open the User Manager, click on edit for your user account and then the plus icon next to the User Certificates section (this will automatically assign the created cert to this user account for your convenience).
Let’s create the OpenVPN and *.vpn.example.com cert first:
Method:Create an internal CertificateDescriptive Name:Acmi John DoeCertificate authority:Acmi VPN Remote AccessKey length:4096Digest Algorithm:SHA512Certificate Type:User CertificateLifetime:3650Country code:AUState:SACity:AdelaideOrganisation:Acme Inc.Email address:john.doe@example.comCommon Name:Acmi John DoeAlternative Names:TYPE=email, VALUE=john.doe@example.comTYPE=email, VALUE=netmaster@example.com
You may add other (pseudo/administrative) e-mail addresses here as an alias so you may even restrict access to certain pages/backends, e.g. allow access to the firewall on fw.vpn.example.com only for members of the netmaster staff (meaning this user needs to have netmaster@example.com as an alternative name). This will be kind of role-based authentication if you extend the ACL in the corresponding shared frontend we will be creating for each of the servers later. However, I don’t want this to become too complex here so this is just some inspiration for more advanced enterprise use you may follow up on later.
Let’s now create the SSLH cert:
Method:Create an internal CertificateDescriptive Name:Acmi-SSLH John DoeCertificate authority:Acmi SSLH GatewayKey length:4096Digest Algorithm:SHA512Certificate Type:User CertificateLifetime:3650Country code:AUState:SACity:AdelaideOrganisation:Acme Inc.Email address:john.doe@example.comCommon Name:Acmi-SSLH John DoeAlternative Names:TYPE=email, VALUE=john.doe@example.comTYPE=email, VALUE=hostmaster@example.com
Same info about the alternative names I mentioned above applies here.
OpenVPN Setup
Create a normal new OpenVPN instance listening on TCP port 1194 (it may use the WAN interface just as normal) using the CA “Acmi VPN Remote Access” and it’s certificate “vpn.example.com” we created above.
I will not go any deeper into this as there are much other (and more sophisticated) how-to’s out there in the net.
Basic HAproxy configuration
We will start with a dummy backend and the second level frontends for HTTPS, HTTPS-auth and SSLH and combine them in a first level frontend instance afterwards.
Hardening against vulnerability
In the general settings tab, you want to add this to the Global Advanced Pass Through field:
# generated 2021-09-18, Mozilla Guideline v5.6, HAProxy 1.8.3, OpenSSL 1.1.0i, intermediate configuration# https://ssl-config.mozilla.org/#server=haproxy&version=1.8.3&config=intermediate&openssl=1.1.0i&guideline=5.6# set default parameters to the intermediate configurationssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparamssl-dh-param-file /conf/dhparam
_tune.ssl.default-dh-param 2048_
# Time-to-first-Byte (TTFB) value needs to be optimized based on# the actual public certificate chain see# https://www.igvita.com/2013/10/24# /optimizing-tls-record-size-and-buffering-latency/tune.ssl.maxrecord 1370
Creating a dummy backend
Being in the backend section of the HAproxy configuration gui, create a new instance called “none”. We will use this backend later as our default destination as it’s actually doing nothing but being a placeholder for everything that does not match elsewhere.
Use the following settings:
Mode:disabledName:noneForwardto:address+portAddress:127.0.0.1Port:80(or any other port which does **not** listen on localhost)Health check method:none
Click on “save”.
Setup SSL redirect on port 80
For convenience reasons you would normally want to setup a redirect from port 80 to 443.
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
sequenceDiagram
Note left of WAN_HTTP: WAN Listening on port 80
WAN_HTTP-->>+ssl-redirect:redirect scheme https code 301
Note right of ssl-redirect: 127.0.0.1 Listening port 8081 Unused port
First, create a backend:
Mode:inactiveName:ssl-redirectForwardto:address+portAddress:127.0.0.1Port:8081(or any other port which does not listen on localhost)Backend pass through:redirect scheme https code 301Health check method:none
Second, create the corresponding primary frontend:
Name:WAN_HTTPDescription:Redirect HTTP traffic to HTTPSListen address:WAN address (IPv4)Port:80SSL Offloading:noBackend server pool:ssl-redirectType:HTTP / HTTPS(offloading)
That was easy.
Implementation of all Frontends (First and Second) and Backends
The first Frontend ‘WAN_443’ is use to share the port 443 wirh first frontend
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
sequenceDiagram
Note left of WAN_443: WAN Listening port 443
rect rgb(204,255,255)
loop < WAN_443 to WAN_443_HTTPS
WAN_443-->>WAN_443_HTTPS:accept-proxy npn http/1.1
end
end
Note right of WAN_443_HTTPS: Listening port 2043
rect rgb(204,229,255)
loop WAN_443 to WAN_443_HTTPS_auth
WAN_443-->>WAN_443_HTTPS_auth:accept-proxy npn http/1.1
WAN_443-->>WAN_443_HTTPS_auth:Client verification CA certificates
end
end
Note right of WAN_443_HTTPS_auth: Listening port 2044
rect rgb(93,173,226)
loop WAN_443 to WAN_443_SSLH dialog
WAN_443-->>WAN_443_SSLH: accept-proxy npn ssh/2.0
end
end
Note right of WAN_443_SSLH: Listening port 2022
rect rgb(213,245,227)
loop WAN_443 to WAN_443_TCP dialog
WAN_443-->>WAN_443_TCP: req.ssl_hello_type 1
WAN_443-->WAN_443_TCP: and req_ssl_sni -i exemple.com
WAN_443-->WAN_443_TCP: and not req_ssl_sni -i -m end ssh.exemple.com
WAN_443-->WAN_443_TCP: and not req_ssl_sni -i -m end vpn.exemple.com
end
end
Note right of WAN_443_TCP: Listening port 2045
Creating the HTTPS frontend instance
Switch to the frontend section and create a new instance using the following settings:
Name:WAN_HTTPSDescription:HTTPS Reverse ProxyExternal address:localhost (IPv4)Port:2043SSL Offloading:yesAdvanced:accept-proxy npn http/1.1Backend Server Pool:none (or use any other webserver backend, e.g. to show custom error pages instead of 503)Type:HTTP / HTTPS(offloading)Client timeout:7200000Use ‘forwardfor’ option:yesAdvanced pass through:# Remove headers that expose security-sensitive information.rspidel ^Server:.*$rspidel ^X-Powered-By:.*$rspidel ^X-AspNet-Version:.*$# add some security related headersrspadd Content-Security-Policy: default-src https: data:'unsafe-inline''unsafe-eval'rspadd X-Frame-Options:SAMEORIGINrspadd X-Content-Type-Options:nosniffrspadd X-Xss-Protection:1; mode=blockCertificate:Ideally choose a wildcard cert you uploaded to the Cert Manager before, e.g. from StartCom/StartSSL. We are choosing “*.example.com” here. Put additional certificates as required.Add ACL for certificate CommonName:NoAdvanced SSL options:no-sslv3
Click on “save”.
Creating the HTTPS-Auth frontend instance
Back in the frontend overview, you may just clone the instance we just created by using the plus icon right next to that line. I will only describe what needs to be changed here:
Name:WAN_HTTPS_authDescription:*.vpn.example.com(HTTPS Reverse Proxy with X.509 Auth)Port:2044Certificate:*.vpn.example.com(this needs to be an official wildcard certificate!)Client verification CA certificates:Acmi VPN Remote Access (which we created before)
Note: You cannot link any CRL here at the beginning because even though you would have created it using the Cert Manager it’d be still empty at the beginning which HAproxy does not like. Add it here as soon as you actually have revoked any certificate.
Creating the SSLH frontend instance
Now we create the third 2nd level frontend which will do SSH routing for us.
Name:WAN_SSLHDescription:*.ssh.example.com(SSL-secured SSH gateway with X.509 authentication)External address:localhost (IPv4)Port:2022SSL Offloading:yesAdvanced:accept-proxy npn ssh/2.0Backend Server Pool:noneType:SSL / HTTPS(TCP mode)Client timeout:7200000Certificate:ssh.example.com (as created before)Add ACL for certificate CommonName:NoAdvanced ssl options:no-sslv3Client verification CA certificates:Acmi SSLH Gateway
Creating the port 443 sharing main frontend instance
Now that you’ve come that far you cannot use any services yet due to the localhost listening we used before. We will change this here.
%%{init: {'securityLevel': 'loose', 'theme':'base'}}%%
sequenceDiagram
Note left of OpenVPN: WAN Listening on port 1194
OpenVPN->>openvpn:To openvpn
Note right of openvpn:No backend openvpn daemon already listening
OpenVPN
Mode:activeName:OpenVPNForwardto:address+portAddress:192.168.178.2(basically your WAN IP running the OpenVPN instance)Port:1194SSL:NoHealth check method:noneConnect timeout:3000Server timeout:7200000Retries:2
%%{init: {'securityLevel': 'strict', 'theme':'base'}}%%
sequenceDiagram
rect rgb(229, 255, 204)
loop TCP
Note left of WAN_443: WAN Listening on port 443
Note over WAN_443,WAN_443_HTTPS: From Main Frontend to Shared Frontend
WAN_443->>WAN_443_HTTPS:tcp-request inspect-delay 5s
WAN_443->>WAN_443_HTTPS:tcp-request content accept if { req.ssl_hello_type 1 } or !{ req.ssl_hello_type 1 }
Note over WAN_443_HTTPS,WAN_HTTPS_BKD: From Shared Frontend To Special Backend From WAN IP to localhost:2043
WAN_443_HTTPS->>WAN_HTTPS_BKD: req.ssl_hello_type 1
WAN_443_HTTPS-->>WAN_HTTPS_BKD: shared Frontend to special backend
end
end
rect rgb(204,229, 255)
loop HTTPS
WAN_HTTPS_BKD-->>WAN_HTTPS: special backend to Second Frontend
WAN_HTTPS_BKD->>WAN_HTTPS:accept-proxy npn http/1.1
Note right of WAN_HTTPS: Listening on 127.0.0.1 port 2043
Note over WAN_HTTPS,backend_01: Host matches docs.example.com
WAN_HTTPS-->>backend_01: SSL offloading
Note right of backend_01: Listening port 443
loop Availability
backend_01->>backend_01: HAPROXY Check
end
Note over WAN_HTTPS,backend_02: Host matches blog.example.com
WAN_HTTPS-->>backend_02: SSL offloading
Note right of backend_02: Listening port 443
loop Availability
backend_02->>backend_02: HAPROXY Check
end
end
end
First, we need to create special backend services for each of the 2nd layer frontends so we can loop back to them from our 1st level frontend instance.
special backends
Mode:activeName:WAN_TCPForwardto:address+portAddress:127.0.0.1Port:2045(the port we used before for this frontend instance)SSL:yesPer server pass thru:send-proxyHealth check method:noneServer timeout:7200000
Mode:activeName:WAN_HTTPSForwardto:address+portAddress:127.0.0.1Port:2043(the port we used before for this frontend instance)SSL:yesPer server pass thru:send-proxyHealth check method:noneServer timeout:7200000
Mode:activeName:WAN_HTTPS_authForwardto:address+portAddress:127.0.0.1Port:2044(the port we used before for this frontend instance)SSL:yesPer server pass thru:send-proxyHealth check method:noneServer timeout:7200000
Mode:activeName:WAN_SSLHForwardto:address+portAddress:127.0.0.1Port:2022(the port we used before for this frontend instance)SSL:yesPer server pass thru:send-proxyHealth check method:noneServer timeout:7200000
After this, let’s finally create the main frontend instance:
Name:WAN_443Description:Sharing port 443Shared Frontend:NoExternal address:WAN address (IPv4)Port:443SSL Offloading:NoBackend Server Pool:noneType:TCPClient timeout:7200000Advanced pass thru:tcp-request inspect-delay 5stcp-request content accept if { req.ssl_hello_type 1 } or !{ req.ssl_hello_type 1 }
To route to the correct frontend, we will create a “shared frontend” for each of our 2nd level frontent (pfSense names it like this, actually this is simply additional configuration to the assigned primary frontend).
So let’s create 4 shared frontends:
Shared Frontend
Name:WAN_443_OpenVPNDescription:OpenVPNShared Frontend:YesPrimary Frontend:WAN_443Backend Server Pool:OpenVPNAccess Control lists:NAME=acl1_1 EXPR=Custom NOT=yes VALUE=req.len 0NAME=acl1_1 EXPR=Custom NOT=yes VALUE=req.ssl_hello_type 1
Name:WAN_443_TCPDescription:TCPShared Frontend:YesPrimary Frontend:WAN_443Backend Server Pool:WAN_TCPAccess Control lists:NAME=acl2_1 EXPR=Custom NOT=no VALUE=req.ssl_hello_type 1NAME=acl2_2 EXPR=Custom NOT=no VALUE=req_ssl_sni -i blog.exemple.comNAME=acl2_3 EXPR=Custom NOT=no VALUE=req_ssl_sni -i docs.exemple.comNAME=acl2_4 EXPR=Custom NOT=yes VALUE=req.ssl_sni -m end -i .vpn.example.comNAME=acl2_5 EXPR=Custom NOT=yes VALUE=req.ssl_sni -m end -i .ssh.example.com
Name:WAN_443_HTTPSDescription:HTTPSShared Frontend:YesPrimary Frontend:WAN_443Backend Server Pool:WAN_HTTPSAccess Control lists:NAME=acl3_1 EXPR=Custom NOT=no VALUE=req.ssl_hello_type 1NAME=acl3_2 EXPR=Custom NOT=yes VALUE=req.ssl_sni -m end -i .vpn.example.comNAME=acl3_3 EXPR=Custom NOT=yes VALUE=req.ssl_sni -m end -i .ssh.example.com
Name:WAN_443_HTTP_authDescription:*.vpn.example.comShared Frontend:YesPrimary Frontend:WAN_443Backend Server Pool:WAN_HTTPS_authAccess Control lists:NAME=acl4_1 EXPR=Custom NOT=no VALUE=req.ssl_hello_type 1NAME=acl4_2 EXPR=Custom NOT=no VALUE=req.ssl_sni -m end -i .vpn.example.com
Name:WAN_443_SSLHDescription:*.ssh.example.comShared Frontend:YesPrimary Frontend:WAN_443Backend Server Pool:WAN_SSLHAccess Control lists:NAME=acl5_1 EXPR=Custom NOT=no VALUE=req.ssl_hello_type 1NAME=acl5_2 EXPR=Custom NOT=no VALUE=req.ssl_sni -m end -i .ssh.example.com
So much for the basic setup! But there is actually no server or web service available right now (beside OpenVPN which should be working right away now). This is what we are going to setup now. But oh wait, of course we obviously miss some DNS stuff so let’s shortly create these canonical name records in your DNS:
_ssh.example.com. IN A <your-WAN-IP-address>
vpn.example.com. IN A <your-WAN-IP-address>
*.vpn.example.com. IN A <your-WAN-IP-address>
Should you be using a dynamic IP address for your WAN device you may also use CNAME records to your DynDNS provider’s name.
Okay, let’s finally start with the examples on how to make internal services available through your ultimate HAproxy setup now.
Make public websites available via SSL offloading
Normal SSL offloading functionality is available creating shared frontends for each backend service an assign WAN_HTTPS as it’s primary frontend.
You may just use the standard pre-defined expression for matching hostnames so route to specific backend web servers based on their URL (first create the backend, then create the secondary frontend).
Put any server certificates in here as required.
You may also want to enable Strict-Transport-Security and Cookie protection here.
Make internal websites available via SSL offloading
A lot of so called SSL-VPN appliances (e.g. Juniper) allow to granularly give access to internal websites without needing any VPN client software. In fact this is nothing else than some sophisticated reverse proxy and we can have pretty much same functionality (on top of the OpenVPN dial-in for more complex remote access requirements) using HAproxy and authentication via X509 user certificates.
The setup is exactly like with the public website described above, only difference is to assign WAN_HTTPS_auth as it’s primary backend.
For better convenience of this service we are using this wildcard certificate *.vpn.example.com together with wildcard DNS record so we can easily add additional backends without changing DNS or adding certs every time (of course this is still an option should you need a different URL, just takes more effort to set up).
Remember to import the user’s certificate and the public cert of your CA into his browser.
Make internal servers console accessible via SSL-tunneled SSH
You can find a lot of information on this kind of feature in the following article from Michel Mayen about routing ssh through HAPROXY
This is the one most of you will be interested in I guess so we’re finally here :-)
Obviously you need to create a new backend first:
Name:ssh_serverMode:activeForwardto:Address+PortAddress:<internal IP or DNS name>Port:22SSL:noHealth check:noneConnection timeout:3000Server timeout:7200000Retries:2
After it, let’s create the corresponding shared frontend:
Name:WAN_SSLH_serverDescription:server.ssh.example.comShared Frontend:yesPrimary Frontend:WAN_SSLHBackend server pool:ssh_serverAccess Control lists:NAME=acl EXPR=Custom VALUE=ssl_fc_npn -i ssh/2.0NAME=acl EXPR=Custom VALUE=ssl_fc_sni_reg server.ssh.example.com```yamlThat’s it!Optionally, you may add SSHFP records to your DNS based on server.ssh.example.com.## SSH access examplesSo, how you gonna access this server from external now? Basically it’s about using the ProxyCommand of your SSH client together with OpenSSL’s s_client command. This is pretty much forward for any Mac or Linux machine.### On WindowsWith [mobaXterm](https://mobaxterm.mobatek.net/download-home-edition.html):Download the plugin [Corkscrew](https://mobaxterm.mobatek.net/plugins/Corkscrew.mxt3) (Corkscrew allows to tunnel TCP connections through HTTP proxies) and put it into Mobaxterm folderIf you want to get the help of the plugin:```bashman corkscrew
Start a local session in mobaXterm, create .ssh directory if it doesn’t exist
vim ~/.ssh/config
Without username/password:
Host * ProxyCommand /bin/corkscrew "proxy ip / domain""port" %h %p
If you’re like me, you also want a shortcut for your most used servers so you don’t need to enter the FQDN and user each time. This is still possible:
Host server
Hostname server.ssh.example.com
User root
The ProxyCommand assumes you stored your CA public cert, your personal public cert and private key to ~/.ssh to handle the X509 authentication which allows you to actually make use of the SSLH gateway (or even access to a specific server behind it as mentioned earlier).
Also note I am not using the openssl installation that comes with OS X but installed a newer version using Homebrew because it gives you some more information and better encryption support. I’m also using Homebrew’s OpenSSH for better SSHFP support, see this page.
Now you can simply SSH into server.ssh.example.com (or just server). Your connection will have strong SSL encryption which you can see directly from the connection output (it’s probably better than most single SSH connections as ECDSA often is not available due to outdated SSH server packages even on fairly new servers). Secondly you are using kind of 2-factor-authentication (first X509 cert + username + password or SSH key) to actually login which makes this a really secure way to access any server in your internal network from the outer world.