Simpler way to configure Oracle VPS as a VPN to get around CGSNAT for node hosting purposes

Continuing the discussion from Did anybody tried oracle free tier as vpn?:

This modified approach avoids messing with iptables rules and accomplishes the same outcome in a drastically simpler and straightforward way, taking advantage of firewalld, that is already running on the oracle linux instances anyway.

Setup goes as follows:

  • Configure firewall on the oracle gateway in the web or cli console, to allow your node’s port and wireguard port, as described in the linked post above

  • Configure Wireguard tunnel, following whatever tutorial you like. Just bare minimum, no preUp/psotDown rules or anything else fancy.

    Example:
    on the server:

    # cat /etc/wireguard/wg0.conf
    [Interface]
    PrivateKey = xxx
    ListenPort = 51820
    Address = 10.143.221.13/32
    
    [Peer]
    PublicKey = yyy
    AllowedIPs = 10.143.221.14/32
    

    on the client:

    # cat /usr/local/etc/wireguard/oracle.conf
    [Interface]
    PrivateKey = zzz
    Address = 10.143.221.14/32
    
    [Peer]
    PublicKey = nnn
    AllowedIPs = 0.0.0.0/0
    Endpoint = oracle_instance_public_ip:51820
    PersistentKeepalive = 25
    

    That’s it, nothing else. Note, here we are setting AllowedIPs to 0.0.0.0/0 – this is to send all traffic originating on the node via VPN, specifically, the inadyn traffic, that would update DDNS if you used one. If you don’t want that – set only server’s address in the allowed IPs instead. In this case there is no need to enable masquerading on the instance below either.

  • Now the packet forwarding bits, without the hard to follow and maintain iptables. Run this script, making adjustments to ports, addresses, or interface names if needed:

    WG_CLIENT_IP=10.143.221.14
    WG_CLIENT_PORT_EXT=28967
    WG_CLEINT_PORT_INT=28967
    WG_IFACE="wg0"
    # Oracle default external zone is called "public", not "external"
    EXT_ZONE="public"
    
    # Allow wireguard connections
    firewall-cmd --zone="$EXT_ZONE" --add-port=51820/udp
    
    # Allow node connections:
    firewall-cmd --zone="$EXT_ZONE" --add-port=$WG_CLIENT_PORT_EXT/udp
    firewall-cmd --zone="$EXT_ZONE" --add-port=$WG_CLIENT_PORT_EXT/tcp
    
    # Enable masquerading on the "$EXT_ZONE" zone oracle has configured. Predefined "external"
    # zone would have had that enabled. This is not needed if you don't want to route all traffic
    # that originates on the node through the wireguard, see above.
    firewall-cmd --zone="$EXT_ZONE" --add-masquerade
    
    # Add forwarding rules for your nodes' port  
    firewall-cmd --zone="$EXT_ZONE" --add-forward-port="port=$WG_CLIENT_PORT_EXT:proto=tcp:toport=$WG_CLEINT_PORT_INT:toaddr=$WG_CLIENT_IP"
    firewall-cmd --zone="$EXT_ZONE" --add-forward-port="port=$WG_CLIENT_PORT_EXT:proto=udp:toport=$WG_CLEINT_PORT_INT:toaddr=$WG_CLIENT_IP"
    
    # add wireguard interface to internal zone
    firewall-cmd --zone=internal --add-interface="$WG_IFACE"
    
    # Review:
    firewall-cmd --get-active-zones
    firewall-cmd --info-zone="$EXT_ZONE"
    

    you shall see something like this:

    # firewall-cmd --get-active-zones
    internal
      interfaces: wg0
    public
      interfaces: enp0s3
    # firewall-cmd --info-zone=public
    public (active)
      target: default
      icmp-block-inversion: no
      interfaces: enp0s3
      sources:
      services: dhcpv6-client ssh
      ports: 51820/udp 28967/udp 28967/tcp
      protocols:
      forward: no
      masquerade: yes
      forward-ports:   
    	port=28967:proto=tcp:toport=28967:toaddr=10.143.221.14
    	port=28967:proto=udp:toport=28967:toaddr=10.143.221.14
      source-ports:
      icmp-blocks:
      rich rules:
    
  • Connect wireguard, startup your node, make sure all works. Then make the firewalld configuration persistent:

    firewall-cmd --runtime-to-permanent
    

Bonus:

Configure alarm on the query BytesToIgw[1d].sum() > 333,000,000,000 on oct_internet_gateway – this way you will get notified if you used up over 10TB/30 of traffic in one day, indicating that you might want to eventually switch to some other vpn service with unmetered egress, as you will likely blow through free allowance.

3 Likes

I use ZeroTier VPN and have just 4 IPTables rules Configured
I find this more robust than OpenVPN or wireguard

This needs a public IPv4, so no solution for people who don’t have one.

No, the Oracle vps does have a public IP. Otherwise it won’t work use this as a cgnat workaround too. Just redirect the traffic from the public oracle up to the zerotier IP of your node.

This locks you to only using VPS you can control (to install Zerotier) and makes it an additional work to switch to other, more suitable purpose-built VPN services.

With full tunnel wireguard or OpenVPN it’s pretty trivial to setup multiple services and just swap endpoint when the connectivity is lost; any service will have schedules or unscheduled downtime. Inadyn will take care of DDNS and node won’t notice anything has happened.

You could arrange the same with zerotier too, but it’s more work, and adds another entity into the mix unnecessarily.

I’m pretty sure the firewalld results in the exact same iptables or nftables rules. The benefit is that you don’t have to write those and instead express your requirements in a more human-like way. Iptables are not designed for humans.

Btw number of iptable rules is not a good metric of anything either :slight_smile:

I like the idea of the alarm, I got hit by a $90 fee when a big test month used 20TB of bandwidth.

2 Likes