Skip to content

Instantly share code, notes, and snippets.

@monkut
Created June 14, 2019 06:58
Show Gist options
  • Save monkut/16d79d98752039c0e36dcb0dbcb0a9b8 to your computer and use it in GitHub Desktop.
Save monkut/16d79d98752039c0e36dcb0dbcb0a9b8 to your computer and use it in GitHub Desktop.
Prepare AWS Client VPN for connecting to a VPC without NAT/IGW

Prepare AWS Client VPN README

Prerequisites

  • AWS Account
  • Linux(like) System
  • awscli

Prepare OpenVPN certificates and Keys

  1. Create a working directory:

    mkdir ~/prepare-aws-vpn-client
  2. Get OpenVPN/easy-rsa:

    OpenVPN/easy-rsa provides simplified RSA key creation/management features

    cd ~/prepare-aws-vpn-client
    git clone https://github.com/OpenVPN/easy-rsa.git
  3. Create the Public Key Infrastructure (PKI)

    cd easy-rsa/easyrsa3
    
    # run `easyrsa init-pki` to build the PublicKeyInfrastructure (PKI)
    ./easyrsa init-pki
  4. Build the Certificate Authority (CA) for issuing the certificate(s) needed:

    ./easyrsa build-ca nopass
    
    # Enter, "rcs-vpn-ca" for Common Name.
    Common Name (eg: your user, host, or server name) [Easy-RSA CA]:rcs-vpn-ca
    
    CA creation complete and you may now import and sign cert requests.
    Your new CA certificate file for publishing is at:
    ~/prepare-aws-client-vpn/easy-rsa/easyrsa3/pki/ca.crt
  5. Create the Server and Client Certificates:

    # create server private key for signing and certificate
    ./easyrsa build-server-full server nopass
    
    # create client private key for signing and certificate
    ./easyrsa build-client-full client1.vpn.tld nopass
    
  6. Collect Server/Client certifications/keys for ease of use:

    mkdir /tmp/aws-vpn/
    
    # copy CA certificate
    cp pki/ca.crt /tmp/aws-vpn/
    
    # collect server cert/key
    cp pki/issued/server.crt /tmp/aws-vpn/
    cp pki/private/server.key /tmp/aws-vpn/
    
    # collect cliet cert/key
    cp pki/issued/client1.vpn.tld.crt /tmp/aws-vpn/
    cp pki/private/client1.vpn.tld.key /tmp/aws-vpn/
    
    # check certs/keys were successfully copied
    ls -lrt /tmp/aws-vpn/

Import Server/Client Certificates and Keys to AWS ACM:

  1. Set AWS_PROFILE:

    export AWS_PROFILE={YOUR APPROPRIATE AWS PROFILE}
  2. Import Server Certificate and Private Key into AWS ACM:

    aws acm import-certificate --certificate file:///tmp/aws-vpn/server.crt --private-key file:///tmp/aws-vpn/server.key --certificate-chain file:///tmp/aws-vpn/ca.crt
  3. Import Client Certificate and Private Key into AWS ACM:

    aws acm import-certificate --certificate file:///tmp/aws-vpn/client1.vpn.tld.crt --private-key file:///tmp/aws-vpn/client1.vpn.tld.key --certificate-chain file:///tmp/aws-vpn/ca.crt
  4. Confirm that server/client certificates and keys were properly imported:

    aws acm list-certificates
    # both server & client1.vpn.tld should be displayed in the output
  5. Create Cloudwatch LogGroup/LogStream for vpn connection logging:

    aws logs create-log-group --log-group-name vpn-client-logs
    aws logs create-log-stream --log-group-name vpn-client-logs --log-stream-name connections
  6. Create the client VPN endpoint:

    aws ec2 create-client-vpn-endpoint --client-cidr-block "10.0.208.0/22" \
        --server-certificate-arn $(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`server`].CertificateArn' --output text) \
        --authentication-options Type=certificate-authentication,MutualAuthentication={ClientRootCertificateChainArn=$(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`client1.vpn.tld`].CertificateArn' --output text)} \ 
        --connection-log-options Enabled=true,CloudwatchLogGroup=vpn-client-logs,CloudwatchLogStream=connections
  7. Associate created ClientVPN Endpoint with VPC:

    NOTE: This expects that at least 1 subnet in the given VPC is tagged 'public'. Assumes only 1 ClientVpnEndpoint exists!

    export RCS_VPCID={YOUR TARGET VPC}
    aws ec2 associate-client-vpn-target-network \
        --client-vpn-endpoint-id $(aws ec2 describe-client-vpn-endpoints --query 'ClientVpnEndpoints[0].ClientVpnEndpointId' --output text) \
        --subnet-id $(aws ec2 describe-subnets --query 'Subnets[?VpcId==`'$RCS_VPCID'` && Tags[?Value==`public`]].SubnetId | [0]' --output text)
  8. Authorize access to VPC for Client VPN endpoint connectionsfor the FULL VPC segment:

    NOTE: Defined CIDR here is specific to prepared VPC, may need to update in your case.

    aws ec2 authorize-client-vpn-ingress \
        --client-vpn-endpoint-id $(aws ec2 describe-client-vpn-endpoints --query 'ClientVpnEndpoints[0].ClientVpnEndpointId' --output text) \
        --target-network-cidr "10.0.0.0/16" \
        --authorize-all-groups
  9. Download the client connection configuration for the created Client VPN endpoint:

    NOTE: Assumes only a single ClientVPNEndpoint

    aws ec2 export-client-vpn-client-configuration --client-vpn-endpoint-id $(aws ec2 describe-client-vpn-endpoints --query 'ClientVpnEndpoints[0].ClientVpnEndpointId' --output text) \
        --query 'ClientConfiguration' --output text > ~/client-configuration.ovpn
    
  10. Add client certification/key information to *.ovpn configuration file:

    echo "cert /tmp/aws-vpn/client1.vpn.tld.crt" >> ~/client-configuration.ovpn
    echo "key /tmp/aws-vpn/client1.vpn.tld.key" >> ~/client-configuration.ovpn 

Connect via VPN

  1. Install openvpn (ubuntu:

    sudo apt install openvpn
  2. Connect to VPN using prepared client-configuration.ovpn:

    sudo openvpn --config ~/client-configuration.ovpn
    
@jwoods943
Copy link

This is a good guide. You also need to move ~/prepare-aws-client-vpn/easy-rsa/easyrsa3/pki/ca.crt -----> /tmp/aws-vpn/, by running:

mv ~/prepare-aws-client-vpn/easy-rsa/easyrsa3/pki/ca.crt /tmp/aws-vpn/

The new versions of the AWS CLI also need to use fileb instead of file in the import section, otherwise you will get an invalid base64 error.

Thank you for the guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment