AWS Client VPN internals

About AWS Client VPN

AWS Client VPN is a managed client-based VPN service provided by AWS. With Client VPN, it is possible to access AWS resources from any location using an OpenVPN-based VPN client.

Recently AWS added ability to use SAML IdP for user authorization and authentication (see image).


However, SAML federation requires you to use proprietary AWS VPN Client which is available only for Windows and macOS. Moreover, the client is a closed source and very limited.

In this post, I will show how it works under the hood and how to connect to it using the native OpenVPN binary.

Update from 25.9.20 – AWS source code found

AWS published changes to the OpenVPN on their S3, with link available in the “About” window. Patch in my repository updated to the official one, everything else is still relevant.

What is wrong with “native AWS client”

  • Available only for the macOS and Windows. OpenVPN itself supports pretty every platform which can establish VPN connections.
  • Closed source. In combination with root access, it adds security risks.
  • VERY limited. No hooks, no timeouts, no log export, nothing at all. Just “import profile” and “Connect”. If things are not working – you have to search for the logs in the /tmp folder (??).
  • Client whitelisting only very few OpenVPN options. If you will try to add any non-whitelisted option to the config – the client will fail to start. It is including inactivity timeout settings, scripting, etc.
  • No documentation about the ability to create customized packages with pre-loaded config

Hopefully, AWS would address some of these limitations in the future and publish source code of their “client”.

How “native client” works

I was using Wireshark and LLDB tools to find out how the client really works. How user flow looks like:

  1. On the first run, you are importing a profile to the AWS VPN Client. Client detecting auth-federate keyword in it and saving config in the ~/.config/AWSVPNClient/OpenVpnConfigs. Special auth-federate keyword is removed at this stage.
  2. The user running the AWS VPN Client and using the “connect” menu to connect.
  3. AWS VPN Client opening a web browser and redirects to the SAML IdP page. After the authorization browser shows “Authentication details received, processing details. You may close this window at any time.” message.
  4. The client connects to the gateway and traffic starts to go via VPN.

Now, let’s take a look at what is going on internally.

  1. The wrapper on Mono starting OpenVPN binary (part of the package) and starts the HTTP server at address.
  2. Using the OpenVPN management interface it is asking to connect to the provided gateway with the username N/A and password ACS::35001. This (of course) fails with an authentication failure, but as failure reason VPN server sends SAML redirect URL.
  3. Wrapper using this URL and opening it in the browser. If SAML flow succeeds – IdP will redirect the browser with POST data to the HTTP POST data contains SAMLResponse field. On this URL mono wrapper capturing it.
  4. Mono wrapper asks OpenVPN to establish connection second time, but now with N/A as username and SAMLResponse + some session data as a password.
  5. AWS VPN server validates them, and if they are looking valid (e.g. signed by corresponding IdP, etc) start the session.

How to connect with OSS OpenVPN to the AWS Client VPN using SAML

I decided to emulate this flow. I started with writing small HTTP server on golang, which listens on and saving SAMLResponse POST form field to the file. The next step was to write a shell wrapper which emulates the activity of the Mono wrapper in the AWS Client. I decided not to use the management interface but to run the OpenVPN binary directly.

Surprisingly I been able to get the connection up, but only with acvc-openvpn binary from the AWS VPN package. So I decided to build OpenVPN myself to debug why it is not working with OSS binary. After some experiments reason was found:

  • Password length in the OSS OpenVPN is up to 128 bytes. SAML response is ~11Kb. I extended this size but got another problem related to the TLS error.
  • After all, I found that the password block is not fitting into TLS_CHANNEL_BUF_SIZE limit in the OpenVPN, so I had to extend it as well.
  • I been able to connect. Eventually i found OpenVPN modified source code and it shows that my changes are similar to AWS one, but they set much higher limits (up to 256Kb). My repo was updated to include AWS patch instead of mine.

Patch is available here. At this point, I was able to connect and use a VPN.


So far my PoC can connect to the VPN Server. After connect, it is working the same way as AWS client. I already tested both TCP and UDP setup, with 443 and 1194 ports. Some things to do (if I will have some time)

  • Make golang wrapper smarter and replace shell wrapper entirely
  • Think how to integrate this with tunnelblick or other OSS UI for the OpenVPN

As usual – patches and contributions are welcome, repository URL is

Tagged , ,

6 thoughts on “AWS Client VPN internals

  1. Bart says:

    Hi, the modified source is available so I’d say that the GPL is not being violated.

    • sammczk says:

      Agree. I was not able to find source (about box is not something i was looking at), so come to that conclusion. Now i updated this article and related gh repo.

      • Bart says:

        Link is difficult to find (even for the AWS ppl), AWS Business support didn’t know so they pointed me to the tech account manager, then tech account manager told me that he’ll ask the legal team and get back to me (after which he just came back with this information) ;>

    • George Yermulnik says:

      Great article. Is it possible to share link to AWS VPN client for Linux please?

  2. deepak says:

    getting belwo error 33: Syntax error: “(” unexpected

  3. deepak says:

    can you plz tell how build openvpn patch with provided patch file in ur github repo

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: