stunnel vpn traffic and ensure it looks like SSL traffic on port 443

Solution 1:

OpenVPN over TLS

Your VPN is using TCP as a transport protocol. The stunnel instance is used to encapsulate the content of the TCP stream in TLS/TCP. You get this protocol stack:

[IP     ]<------------------------>[IP     ]
[OpenVPN]<------------------------>[OpenVPN]
            [TLS   ]<~~~~~>[TLS]
[TCP    ]<->[TCP   ]<----->[TCP]<->[TCP    ]
[IP     ]<->[IP    ]<----->[IP ]<->[IP     ]
[       ]   [      ]       [   ]   [       ]
 Server      stunnel      stunnel  Client

Between the stunnel instances you have this protocol stack on the wire:

[IP      ]
[OpenVPN ]
[TLS     ]
[TCP(443)]
[IP      ]
[...     ]

As the TLS encrypts its payload, an attacker can only see:

[???     ]
[TLS     ]
[TCP(443)]
[IP      ]
[...     ]

So yes, it is plain TLS traffic (it could be HTTP/TLS, SMTP/TLS, POP/TLS or anything else for someone looking at the traffic but it looks a lot like HTTP/TLS as the TCP port 443 is used). You can check this by using wireshark: record the traffic between the stunnel instances. In the wireshark UI (right button on a packet of the stream), you can ask wireshark to interpret the traffic as TLS: it will recognise it as TLS traffic (you will see the different TLS messages but not the payload of the TLS session).

You might want to use SNI in the client in order to look like what a modern browser would do. You might want to use ALPN as well but stunnel currently does not handle that.

OpenVPN with builtin TLS

In comparison, if you are using OpenVPN, you will have something like this:

[IP      ]
[OpenVPN ]
[TCP     ]
[IP      ]
[...     ]

Which looks like this:

[???     ]
[OpenVPN ]
[TCP     ]
[IP      ]
[...     ]

The builtin TLS layer does not encapsulate the (IP, Ethernet) packets but is only used for setting up the session and authenticating:

[TLS     ]
[OpenVPN ]
[TCP     ]
[IP      ]
[...     ]

In this case, your traffic does not look like a plain TLS traffic but is obviously OpenVPN. If you interpret this traffic as OpenVPN in wireshark, you will recognise the OpenVPN messages and inside of them the TLS messages (but not the payload).

Warning

You should be aware that if a passive attacker will not be able to tell that your remote server is in fact an OpenVPN server, an active attacker will be able to find this out: simply by connecting to your server over TLS, he will be able to confirm that it is not a HTTP/TLS server. By trying to speak the OpenVPN protocol, he will be able to detect that your server is a OpenVPN/TLS server.

OpenVPN over TLS with client authentication

It you are worried about this you could enable TLS client authentication: an attacker will not be able to initiate a working TLS session and will not be able to guess which payload is encapsulated over TLS.

Warning:* I'm not talking about the builtin TLS support in OpenVPN (see above for en explanation about why it won't help you).

Multiplexed OpenVPN/TLS and HTTP/TLS

Another solution is to serve both HTTP and OpenVPN over the TLS session. sslh can be used to automatically detect the payload of the protocol and dispatch either to a plain HTTP/TCP server or you OpenVPN/TCP server. The server will look like standard HTTP/TLS server but someone trying to speak OpenVPN/TLS with this server will be able to detect that it is in fact a OpenVPN/TLS server as well.

        either OpenVPN/TCP
          or HTTP/TCP       
[1].---------.     .------.HTTP/TCP.-------------.
-->| stunnel |---->| sslh |------->| HTTP server |
   '---------'     '------'|       '-------------'
                           |       .----------------.
                           '------>| OpenVPN server |
                        OpenVPN/TCP'----------------'

[1]= Either OpenVPN/TLS/TCP or HTTP/TLS/TCP

OpenVPN over HTTP CONNECT over TLS

Another solution is to use a standard HTTP/TLS server and use HTTP CONNECT/TLS to connect to the OpenVPN server: it will look like a standard HTTP server. You can even require authentication of client in order to authorise the HTTP CONNECT request (squid should be able to do this).

OpenVPN has an option to use a HTTP Proxy:

http-proxy proxy.example.com

You should be able to combine this with a stunnel instance connecting to a remote HTTPS PROXY:

http-proxy 127.0.0.1 8443
remote vpn.example.com

Which would implement this protocol stack:

[IP     ]<------------------------>[IP     ]
[OpenVPN]<------------------------>[OpenVPN]
            [HTTP  ]<------------->[HTTP   ]
            [TLS   ]<~~~~~>[TLS]
[TCP    ]<->[TCP   ]<----->[TCP]<->[TCP    ]
[IP     ]<->[IP    ]<----->[IP ]<->[IP     ]
[       ]   [      ]       [   ]   [       ]
 Server    HTTPS PROXY     stunnel   Client

Solution 2:

ysdx's answer is great, and describes very well how the traffic will look on the wire.

Left unmentioned, however, is that traffic analysis can go a long way toward identifying applications.

Let's assume that your OpenVPN connection looks just like an https connection on the wire, so an attacker cannot read the byte stream and know what kind of connection it is.

A typical https connection won't live too awfully long. Maybe your browser keeps a connection open to your mail server, I don't know. In general though, there will be lots of relatively short connections to a lot of diverse remote servers.

OTOH, the OpenVPN connection might live for hours or days, and will send a lot of data back and forth to the openvpn server.

You could mitigate the long-lived connection by periodically dropping and restarting the connection. This presumably has implications for your application traffic, but might be workable. The pattern of lots and lots of traffic going between you and the openvpn server, however, is going to be a lot harder to camouflage.