1

I'd like to share a VPN connection on my Linux Mint host, with a guest connected directly via ethernet. This seems to be trivial on a Windows host. However the only methods I've seen on Linux are through IP masquerading and/or modifying the firewall directly, which seems dangerous, prone to error, and hard to undo. Is there a method or third-party tool that works similar to how Windows does it?

What I've tried so far is:

  1. open the "Advanced Network Configuration" tool (nm-connection-editor) and then for the ethernet connection, change the IPV4 method from Automatic (DHCP) to Shared to other computers
  2. use ifconfig on the host to figure out the gateway IP of the ethernet connection (it was 10.42.0.1 in my case)
  3. set the gateway IP on the guest to 10.42.0.1
  4. configure the guest device to use the static IP 10.42.0.100 (so the host doesn't need to set up a DHCP server)

Now at this point, I can SSH into the guest device via 10.42.0.100, confirming that there is some sort of connection. However, it doesn't seem like the guest device has any connection to the public internet.

3
  • If your two machines are on the same network you can use hardware VPN and then sharing the connection is fairly easy
    – anon
    Commented Aug 1, 2022 at 3:42
  • what do you mean by hardware VPN? You mean like one of those routers with build-in VPN support? Commented Aug 1, 2022 at 4:18
  • Yes. I use a Cisco RVxx series and it has VPN built in. I do not use the Workstation Operating System.
    – anon
    Commented Aug 1, 2022 at 4:22

2 Answers 2

0

So I found a great detailed guide here, and it turns out I was way over-complicating it. The answer was to simply set the guest/client to use automatic DHCP (instead of a static IP), and everything else was handled automagically! Thanks linux!

I also confirmed that my host's VPN kill-switch worked properly, and the client had zero internet when I disconnected the VPN on the host.

(I originally thought that getting DHCP working would be a pain, after reading two stackexchange answers here and here)

Note that the guide above also details how to get it working with a static client IP, but unfortunately those steps didn't work for me. When I would try to SSH in, I would get "no route to host" errors. Ideally I would have wanted a static IP since my client is a raspberry pi, and I wanted a headless setup, but plugging in an external monitor to get the client IP was a small compromise.

(I think the previously mentioned guide involving editing firewalls was actually mainly about getting a "VPN kill-switch" working. But since my host already has a VPN kill-switch, I actually didn't need all that. In fact I think I could have gotten the 10.42.0.100 static IP working if I had simply enabled IP forwarding, but I didn't want to mess with my setup further)

0

Linux makes this very easy, there's no need to re-invent the wheel.

If you have doubts of which network interfaces are used, you could execute the commands ifconfig or ip addr on a Linux terminal to see the list.

This script will back up the original configuration, apply the necessary changes, and provide a menu to restore backups if needed. Additionally, it will display the required configuration steps for the clients.

On a Linux terminal (the machine on the VPN) add the following script using the editor nano or vi.

Using nano:

sudo nano vpn_connection_sharing.sh

Or using vi:

sudo vi vpn_connection_sharing.sh

In vi, press i to enter insert mode before pasting the script content.

Copy and paste the following script content into the editor. The PASSWORD is set to "ChangeThis", MAKE SURE TO CHANGE IT!!!, you could also change the SSID, by default it's set to "VPN":

#!/bin/bash

# Define variables
BACKUP_DIR="/etc/network-config-backups"
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="${BACKUP_DIR}/network-config-backup_${DATE}.tar.gz"
SSID="VPN"
PASSWORD="ChangeThis"  # Change this to a secure password

# Create a backup
create_backup() {
    echo "Creating backup of current network configuration..."
    mkdir -p ${BACKUP_DIR}
    tar -czvf ${BACKUP_FILE} /etc/sysctl.conf /etc/iptables/rules.v4
    echo "Backup created at ${BACKUP_FILE}"
}

# List and restore backups
restore_backup() {
    echo "Available backups:"
    select file in ${BACKUP_DIR}/*.tar.gz; do
        if [ -f "$file" ]; then
            echo "Restoring backup from $file..."
            tar -xzvf "$file" -C /
            echo "Backup restored from $file"
            break
        else
            echo "Invalid selection. Try again."
        fi
    done
}

# Enable IP forwarding
enable_ip_forwarding() {
    echo "Enabling IP forwarding..."
    if ! grep -q '^net.ipv4.ip_forward=1' /etc/sysctl.conf; then
        echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
    else
        sudo sed -i 's/^#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
    fi
    sudo sysctl -p
    echo "IP forwarding enabled."
}

# Configure iptables
configure_iptables() {
    echo "Configuring iptables for NAT..."
    sudo iptables -t nat -A POSTROUTING -o ${VPN_INTERFACE} -j MASQUERADE
    sudo iptables -A FORWARD -i ${SHARED_INTERFACE} -o ${VPN_INTERFACE} -j ACCEPT
    sudo iptables -A FORWARD -i ${VPN_INTERFACE} -o ${SHARED_INTERFACE} -m state --state RELATED,ESTABLISHED -j ACCEPT
    sudo mkdir -p /etc/iptables
    sudo sh -c "iptables-save > /etc/iptables/rules.v4"
    echo "iptables configured."
}

# Set up Wi-Fi hotspot
setup_wifi_hotspot() {
    echo "Setting up Wi-Fi hotspot..."
    nmcli dev wifi hotspot ifname ${SHARED_INTERFACE} ssid ${SSID} password ${PASSWORD}
    echo "Wi-Fi hotspot set with SSID: ${SSID}"
}

# Display client configuration instructions
display_client_instructions() {
    echo "Client Configuration Instructions:"
    echo "1. Set the client device to obtain an IP address automatically (via DHCP)."
    echo "2. Connect the client device to the Wi-Fi network named '${SSID}' with the password '${PASSWORD}'."
    echo "The client device should now be able to connect to the internet through the Linux host's VPN."
}

# Select network interfaces
select_interfaces() {
    interfaces=$(ip -o link show | awk -F': ' '{print $2}')
    
    echo "Select your VPN interface (usually an Ethernet interface):"
    PS3="Please select the VPN interface: "
    select vpn in ${interfaces}; do
        if [[ -n "$vpn" && $(iw dev $vpn info 2>/dev/null) == "" && $vpn != lo && $vpn != docker0 && $vpn != virbr0 ]]; then
            VPN_INTERFACE=$vpn
            echo "Selected VPN interface: $VPN_INTERFACE"
            break
        else
            echo "Invalid selection or not an Ethernet interface. Try again."
        fi
    done

    echo "Select your Wi-Fi interface:"
    PS3="Please select the Wi-Fi interface: "
    select shared in ${interfaces}; do
        if [[ -n "$shared" && $(iw dev $shared info 2>/dev/null) != "" ]]; then
            SHARED_INTERFACE=$shared
            echo "Selected Wi-Fi interface: $SHARED_INTERFACE"
            break
        else
            echo "Invalid selection or not a Wi-Fi interface. Try again."
        fi
    done
}

# Main script
echo "VPN Connection Sharing Script"
PS3="Please select an option: "
options=("Create Backup and Apply Changes" "Restore Backup" "Exit")
select opt in "${options[@]}"; do
    case $opt in
        "Create Backup and Apply Changes")
            create_backup
            select_interfaces
            enable_ip_forwarding
            configure_iptables
            setup_wifi_hotspot
            display_client_instructions
            break
            ;;
        "Restore Backup")
            restore_backup
            break
            ;;
        "Exit")
            break
            ;;
        *) echo "Invalid option $REPLY";;
    esac
done

Save the file and exit the editor.

In nano:

  1. Press Ctrl + O to save.
  2. Press Enter to confirm the filename.
  3. Press Ctrl + X to exit.

In vi:

  1. Press Esc to exit insert mode.
  2. Type :wq and press Enter to save and exit.

Make the script executable:

chmod +x vpn_connection_sharing.sh

Run the script:

sudo ./vpn_connection_sharing.sh

Client configuration instructions:

  1. Set the client device to obtain an IP address automatically (via DHCP).
  2. Connect the client device to the Linux host via ethernet or Wi-Fi (VPN).

The client devices should now be able to connect to the internet through the Linux host's VPN. That's it!

Enjoy!

1
  • The script works, it's easy for everyone, and it's safe. I added mine to systemctl enable, that way I connect some devices to my work VPN, and some through my personal connection, keeping my private life out of the office.
    – Max Haase
    Commented Jun 18 at 4:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .