Virtual Private Network (VPN) Examples in NeST

This directory contains examples to demonstrate how to use Virtual Private Network (VPN) in NeST.

IMPORTANT

Before running the examples, you will need to install OpenVPN and Easy-RSA. You can do this by running the following command in your terminal:

sudo apt install openvpn easy-rsa

1. vpn-point-to-point-3.py

This program emulates point to point networks that connect two hosts h1 and h2 via two routers r1 and r2. Five ping packets are sent from h1 to h2 once using Using the VPN endpoint address and once using Using the public address, and the success/failure of these packets is reported. It is similar to point-to-point-3.py available in examples/basic-examples, the only difference is that we use connect_vpn API to create VPN tunnel between nodes.

Source code

  1# SPDX-License-Identifier: GPL-2.0-only
  2# Copyright (c) 2019-2023 NITK Surathkal
  3
  4########################
  5# SHOULD BE RUN AS ROOT
  6########################
  7from nest.topology import *
  8from nest.topology.network import Network
  9from nest.topology.address_helper import AddressHelper
 10from nest.topology.vpn import connect_vpn
 11
 12# This program emulates point to point networks that connect two hosts `h1`
 13# and `h2` via two routers `r1` and `r2`. Five ping packets are sent from `h1`
 14# to `h2` once using Using the VPN endpoint address and once using Using the public address,
 15# and the success/failure of these packets is reported. It is similar to
 16# `ah-point-to-point-3.py` available in `examples/address-helpers`, the only
 17# difference is that we use `connect_vpn` API to create VPN tunnel between nodes.
 18
 19##############################################################################
 20#                              Network Topology                              #
 21#                                                                            #
 22#        5mbit, 5ms -->          5mbit, 5ms -->          5mbit, 5ms -->      #
 23# h1 -------------------- r1 -------------------- r2 -------------------- h2 #
 24#     <-- 10mbit, 100ms       <-- 10mbit, 100ms       <-- 10mbit, 100ms      #
 25#                                                                            #
 26##############################################################################
 27
 28# Create two hosts `h1` and `h2`, and two routers `r1` and `r2`
 29h1 = Node("h1")
 30h2 = Node("h2")
 31r1 = Router("r1")
 32r2 = Router("r2")
 33
 34# Set the IPv4 address for the networks.
 35# Note: this example has three networks: one on the left of `r1`, second
 36# between the two routers, and third on the right of `r2`.
 37n1 = Network("192.168.1.0/24")  # network on the left of `r1`
 38n2 = Network("192.168.2.0/24")  # network between two routers
 39n3 = Network("192.168.3.0/24")  # network on the right of `r2`
 40
 41# Connect `h1` to `r1`, `r1` to `r2`, and then `r2` to `h2`
 42# `eth1` and `eth2` are the interfaces at `h1` and `h2`, respectively.
 43# `etr1a` is the first interface at `r1` which connects it with `h1`
 44# `etr1b` is the second interface at `r1` which connects it with `r2`
 45# `etr2a` is the first interface at `r2` which connects it with `r1`
 46# `etr2b` is the second interface at `r2` which connects it with `h2`
 47(eth1, etr1a) = connect(h1, r1, network=n1)
 48(etr1b, etr2a) = connect(r1, r2, network=n2)
 49(etr2b, eth2) = connect(r2, h2, network=n3)
 50
 51# Assign IPv4 addresses to all the interfaces in the network.
 52AddressHelper.assign_addresses()
 53
 54# Set the link attributes: `h1` --> `r1` --> `r2` --> `h2`
 55eth1.set_attributes("5mbit", "5ms")  # from `h1` to `r1`
 56etr1b.set_attributes("5mbit", "5ms")  # from `r1` to `r2`
 57etr2b.set_attributes("5mbit", "5ms")  # from `r2` to `h2`
 58
 59# Set the link attributes: `h2` --> `r2` --> `r1` --> `h1`
 60eth2.set_attributes("10mbit", "100ms")  # from `h2` to `r2`
 61etr2a.set_attributes("10mbit", "100ms")  # from `r2` to `r1`
 62etr1a.set_attributes("10mbit", "100ms")  # from `r1` to `h1`
 63
 64# Set default routes in `h1` and `h2`. Additionally, set default routes in
 65# `r1` and `r2` so that the packets that cannot be forwarded based on the
 66# entries in their routing table are sent via a default interface.
 67h1.add_route("DEFAULT", eth1)
 68h2.add_route("DEFAULT", eth2)
 69r1.add_route("DEFAULT", etr1b)
 70r2.add_route("DEFAULT", etr2a)
 71
 72# Set up the VPN network with a private IPv4 address range.
 73# Make sure the chosen address range is not overlapping with any existing subnets on the network.
 74vpn_network = Network("10.200.0.0/24")
 75
 76# For this address range the IP block 10.200.0.[0-3] is reserved for the OpenVPN server itself.
 77# The IP block 10.200.0.[4-7] is assigned to the first client, and subsequent clients are allocated
 78# consecutive IP addresses like 10.200.0.[8-11], [12-15], [16-19], and so on.
 79
 80# Connect the VPN server and multiple clients using the `connect_vpn` API.
 81# By default, OpenVPN will work with Layer 3 and create a UDP tunnel using it's default port 1194.
 82# The `network` parameter specifies the network to allocate VPN endpoint addresses from.
 83# In this example, `vpn_network`, which is "10.200.0.0/24", is used for VPN endpoint addressing.
 84
 85# Node `h1` acts as the VPN server and is assigned the IP address 10.200.0.1.
 86# When a client (e.g., `h2`) initiates a connection to the server on the designated port,
 87# it is allocated the VPN endpoint IP address 10.200.0.6 after the initial TLS handshake.
 88
 89# Now, we establish the VPN connection between `h1` (VPN server) and `h2` (VPN client)
 90# using the `connect_vpn` API.
 91# The `connect_vpn` API returns the tunnel endpoints for `h1` (h1tun) and `h2` (h2tun).
 92(h1tun, h2tun) = connect_vpn(h1, h2, network=vpn_network)
 93
 94# Once the VPN is established, we have created a secure alternate path between the nodes.
 95# This path is addressed using the tunnel endpoints which belongs to same private network.
 96# We have the flexibility to control which network traffic passes between the nodes over the VPN,
 97# and which traffic should go independently, not using the VPN.
 98
 99# Using the VPN endpoint address to access `h2` from `h1`.
100h1.ping(h2tun.address)
101
102# Using the public address to access `h2` from `h1`.
103# This traffic will not be sent through the VPN.
104h1.ping(eth2.address)