OpenVPN – How to Modify Incoming Traffic or Payload with Custom Script

openvpn

I recently setup OpenVPN with Dnsmasq as DNS and wanna do something I can't seem to find any info about.

Here's my current understanding based also on what I've currently setup on my server.

A. Client connects to OpenVPN, say from a phone

B. Clients sends traffic i.e opens a website, say YouTube

C. OpenVPN server takes the request.

D. Forwards the request to destination server i.e YouTube.

E. YouTube responds back.

F. OpenVPN forwards response to client from A

Of course the above is oversimplified.

What I want to do?

In between the stages C and D, as in after OpenVPN takes the request (or gets a response from destination server i.e D->C), I want to process the actual data.

For example, a typical use case.

In between D and C, I want to pass the payload to, for example, a Python script, change all "I love you" text in the webpage html to "I hate you" before the payload is wrapped up and sent to client.

Question

Are there any form of "Life Cycle Hooks" with OpenVPN where I can basically listen to and alter the payload of a request?

I understand any inbound or outbound connection from OpenVPN is 'fort knox' secured. I'm interested in the point where the response payload is sitting naked on the server.

What are my available options? Do I need to use a different package/software to advice achieve such results?

Best Answer

Your idea is infeasible for several reasons:

1)

As far as I remember there is not a feature in OpenVPN itself to pipe data from a VPN connection into a custom process, before forwarding.

For quick reference: Check out where TCP/IP is being used in the OSI stack.

OpenVPN resides on layer 3 of the OSI stack (Network layer), while TCP packages belongs on layer 4 (Transport layer).

Your question is for this reason alone outside of scope of what OpenVPN wants to achieve.

The only thing you can manipulate with is what happens when a client connects to the server or disconnects.

Those situations can be defined in your server configuration file through the following settings:

# client connected to VPN server
client-connect "/script/client_connect.sh"

# client disconnected from VPN server
client-disconnect "/script/client_disconnect.sh"

All the environmental variables that are available to your custom script is available here:

https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/#scripting-and-environmental-variables

But in essence the only information you can monitor is which client certificate was used to connect to the server and which ip address was assigned to the client and then make some custom logic on server depending on who connects and what to do when they disconnect again.

One typical setup could be to implement a dynamic DNS server side or do some custom routing, like fail-over routing depending on which VPN connection is up.

2)

Referring to this diagram of a IPv4 packet from WikiPedia:

Schematics of a IPv4 packet

In essense what you want todo is to manipulate the data field, depending on source or destination address.

This is also known as the man-in-the-middle attack.

As you have found out it hard todo it by listening on the OpenVPN interface as all content is encryptet. What happens is that IPv4 packet destined for the Internet is encapsulated in another IPv4 packet, which is destined for the OpenVPN server.

The encapsulated IPv4 packet is stored in the data field in the above diagram.

It is the decapsulated packet that is forwarded to the Internet from the VPN server.

However there is a caveat:

I presume the VPN client does not have a public ip address. This means NAT translation is envolved and the source address is rewritten to be that of the VPN server before any host is contacted on the Internet.

Likewise when the host reply back with an answer the we have the destination IPv4 address is the same as the VPN server.

This means that in order to manipulate with the data field we need to keep track of which ports are being used in the network address translation table (aka the NAT).

The ports used is normally dynamic in nature as more than one VPN client can connect to Internet via VPN and NAT and every TCP session (mail, web, ssh whatever) uses a diffrent port.

So if you want manipulate the decrypted TCP packet it has to happen after decryption, but before it is translated in the NAT.

In theory you can intercept the packet using iptables, but it is non-trivial when VPN and NAT resides on the same machine.

Another approach is to attack the encrypted OpenVPN traffic directly, since you control the OpenVPN server means you also control which certificates and private keys are being used on both server and client.

This is doable as a strait-up classic man-in-the-middle attack. I don't know how this is done though. :-)

... but this leads me my last argument:

3)

Most traffic on the Internet is TLS encryptet.

So even after you have decryptet the OpenVPN traffic there is another layer of encryption you have to beat in order to manipulate the content of the data field.

This part is even harder to attack than just attacking the encrypted OpenVPN traffic as you not in control of the encryption keys used for the session.

Even if you tried to decrypt the TLS traffic and reencrypt the content so it looks like for the end user that the encrypted traffic did indeed originate from YouTube or whatever then it would still be futile, since certificate you use to encrypt the https traffic is not trusted by the browsers on the end users computers.

This alone renders your man-in-the-middle attack futile.

Now this is as close to a complete answer to your question.

There are other angles to attack a TCP session, but now we are going it an advanced field that belongs in a forum full of security experts.

That part is WAY beyond my qualifications. :-)

Related Topic