NetworkManager is the system daemon which manages network connections under Fedora, Red Hat and many other popular distro. It supports cable, wireless, mobile broadband, DSL and VPN connections. While cable, wireless, mobile broadband and DSL connections operate at data link level, VPN’s are tunnels over pre-existing ethernet connections; these virtual networks are called private because the packets exchanged through these tunnels are encrypted and, thus, should be private to the connection endpoints.
OpenVPN is a software which implements the concept of VPN through SSL/TLS encryption performed by a userspace process (this differs, for example, from IPSec, which encapsulates packets at IP level). An OpenVPN server process listens usually on port 1194 (TCP or UDP, depending on setup) for incoming connections. When a client connects to the server they authenticate each other by exchanging SSL certificates signed by the same Certification Authority. This connection can be performed through a proxy, provided that the proxy allows the client to CONNECT to the destination port (1194) of the server. Usually, proxies do not allow this. A method to bypass this problem is to make the sever listen on port 443 (i.e. the port assigned to https protocol), where clients are generally allowed to do a CONNECT.
But, then, if you configured your OpenVPN server to listen on port 443, how do you tunnel through the proxy? Well, OpenVPN natively supports the connection through proxy, so one solution is to configure OpenVPN as a system service and start it on boot (or by hand as root anytime you need it). NetworkManager does not allow a user to specify a proxy server to be used when connecting to OpenVPN. If you really want/need to use NetworkManager to connect to your OpenVPN server, then all you need to do is get a tunnel through the proxy up and running before you try to connect, and then configure NetworkManager to connect to that tunnel, instead of the final server.
One effective and easy way to do this as a normal user (no need for root privileges) is to use the socat command:
socat tcp-listen:<local port>,fork \
proxy:<proxy server>:<OpenVPN server>:<OpenVPN server port>,\
proxyport=<proxy port>,proxyauth=<proxy username>:<proxy password>
e.g.:
$ socat tcp-listen:1194,fork \
proxy:proxy.localdomain:ovpnsrv.example.com:443,\
proxyport=8080,proxyauth=myuser:mypasswd
In this example, I assumed the server is listening on port 443. Now all you have to do is configure NetworkManager VPN connection as you would if you had no proxy in the middle, but specify:
localhost:1194
as the server address. socat will tunnel the connection through the proxy by performing a CONNECT on ovpnsrv.example.com:443, and mapping it on local port 1194.
If you don’t want to start socat by hand every time, you can put that line into some startup script or use xinetd to launch the tunenl on-demand (which is more elegant):
- install xinetd
- configure xinetd
- restart xinetd
The configuration file should be somethig similar to the following:
[root@myhost:/etc/xinetd.d]# cat socat-openvpn
service socat-openvpn
{
disable = no
id = socat-openvpn
type = UNLISTED
wait = no
socket_type = stream
user = some_valid_user
group = some_valid_group
server = /usr/bin/socat
server_args = - proxy:proxy.localdomain:ovpnsrv.example.com:443,proxyport=8080,proxyauth=myuser:mypasswd
port = 1194
bind = 127.0.0.1
only_from = 127.0.0.1
}
If you want to share this tunnel with other machines, you can omit the only_from directive (or populate it with a comma-separated list of allowed clients) and maybe bind on other IPs.
Note the dash (-) in the server_args that substituted the directive tcp-connect:1194. xinetd listens on port 1194 and accepts incoming connection, then launches socat and connects the socket of the established connection to the stdin of socat. The dash in the command line means “listen on stdin”. The command lsof on a running socat started by xinetd shows this:
[root@myhost:/etc/xinetd.d]# ps -ef | grep socat
someuser 15636 15632 0 17:05 ? 00:00:00 socat - proxy:proxy.localdomain:ovpnsrv.example.com:443,proxyport=8080,proxyauth=myuser:mypasswd
[root@myhost:/etc/xinetd.d]# lsof -nPp 15636
[...]
socat 15636 someuser 0u IPv4 436618 0t0 TCP 127.0.0.1:1194->127.0.0.1:58822 (ESTABLISHED) # stdin
socat 15636 someuser 1u IPv4 436618 0t0 TCP 127.0.0.1:1194->127.0.0.1:58822 (ESTABLISHED) # stdout
socat 15636 someuser 2u IPv4 436618 0t0 TCP 127.0.0.1:1194->127.0.0.1:58822 (ESTABLISHED) # stderr
socat 15636 someuser 3u IPv4 435194 0t0 TCP 192.168.10.101:39661->proxy.localdomain:80 (ESTABLISHED) # proxy connection
[root@myhost:/etc/xinetd.d]# ls -l /proc/15636/fd/
total 0
lrwx------ 1 someuser someuser 64 Nov 22 17:05 0 -> socket:[436618]
lrwx------ 1 someuser someuser 64 Nov 22 17:05 1 -> socket:[436618]
lrwx------ 1 someuser someuser 64 Nov 22 17:05 2 -> socket:[436618]
lrwx------ 1 someuser someuser 64 Nov 22 17:05 3 -> socket:[435194]