Software Defined Networking
Tags: networking, cloud, python, fastapi
Published: 2023-05-19 10:55:28

_Disclaimer: None of the links are affiliates. _

## Introduction

Before I delve into what Software-defined networking is and how I stumbled upon this. Let me explain the problem statement and all of the solutions I tried before I finally arrived at this solution. 

I am hoping there is another person scratching their head trying to figure out how to go about this and hope this guide saves them a lot of time. 

## Problem statement 

I have a piece of hardware (you can assume, an Arduino board and a motor driver circuit connected to the Arduino) connected to my laptop and I have a UI created in React that will allow me to control the pins of my Arduino. Let's say, I want to control the PWM output of my Arduino board, which will, in turn, modify the speed at which the motor is running. 

I have this react UI deployed on a [digitalocean](https://www.digitalocean.com/) droplet and I wanted the UI to control the Arduino. I have written a thin flask layer between the Arduino and the React which will run on a Gunicorn server in my localhost. 

The solutions discussed are very much applicable to any of the Python web frameworks - FastAPI, flask, Django, and others. 
Also, to other cloud providers like Azure, AWS, and Heroku. 
Even if you want to replace the frontend with another low-code platform, that is also fine. 

## Solution 1

This was the first thing I tried. Put up an Nginx server and tried to ping from the droplet, but it failed fast. The IP address of my laptop is not visible to the public. I did not want to compromise the security, so I didn't pursue it further.  


![With Nginx](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2ta8llxb799p8xbj0bo.jpg)

Normally, if I wanted to run a react app with a Flask backend this is what I would do. Have my Flask server running on a digital ocean droplet and have the react application also be on digital ocean and both are on the same VPC (Virtual Private Cloud). Nginx will be front-facing the incoming traffic on the digital ocean. But here, I don't need to expose my API server to the internet since they are on the same VPC.

## Solution 2

From the first failure, I understood I wanted to bring my laptop into the same network as my digital ocean droplet. This will make my laptop visible to the droplet without causing security issues to my laptop. Naturally, VPN was my first choice. 

The architecture I created was to have another droplet that will act as a VPN Access server. The droplet running my react UI and the droplet running the VPN access server will be on the same VPC.  I will have to install a VPN client so that I can bring my laptop into the same network as the React UI. 


![With OpenVPN Server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xfj9l3y2lf9ch06zg7b.jpg)


I had a guide from the digital ocean on how to set this up. Attaching some reference links: 
[vpn-access-server-setup](https://openvpn.net/vpn-server-resources/digital-ocean-quick-start-guide/)
[how-to-configure-the-openvpn-access-server](https://openvpn.net/vpn-server-resources/how-to-configure-the-openvpn-access-server/)

The benefits of using such a network architecture are: 

- Quickly extend your private networking to remote users and other sites.
- Create hub-and-spoke network topology, site-to-site, user-to-cloud, and various other secure VPN connections.
- Provide secure, remote access to applications deployed on the private cloud.

I did not test this out, but I can already see the pain of doing all this configuration. But I do not want to go through this for a prototype. 

While this experiment was not a failure, I was still searching if there was another more robust solution than this one. 

## Solution 3

During a brainstorming session with a colleague, he suggested why don't we use a Zero Config VPN instead of setting up a VPN Server. He suggested the name ZeroTier which actually is providing a software-defined network solution. (I will write more once I have the solution finalized) 

I went back to the drawing board. What ZeroTier does is, it creates a private network and gives me a network id. If I have the Zerotier client installed on my system, my system (droplet or laptop, or mobile phone) can communicate with other resources in the network. All this, while staying private. 


![With Zerotier](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ql0hplpyflqscq4rzmm.jpg)

The Zerotier dashboard is much easier to manage, and I get up to 25 nodes on the free tier. 

## Test Procedure and Result

**Step 1:** Create an account on [Zerotier](https://my.zerotier.com/)
**Step 2:** Create a network. 
**Step 3:** Install the client on your laptop, on the droplet, or on your mobile phone. 
**Step 4:** Open the Zerotier client application and click "Join a Network". key in the 16-character network id when prompted.  
**Step 5:** Go back to the Zerotier dashboard and authorize the new connection. 
**Step 6:** Voila, you are done!

**Step 7:** But not just yet. In my case, my flask application was listening on port 8000 and I had to go to Windows firewall settings as an administrator and create an inbound rule to allow port 8000 within the private network. 

**Step 8**: You can call the rest API from any device if they have joined the network! 

If you want more detailed documentation to setup Zerotier, check out their docs [here](https://zerotier.atlassian.net/wiki/spaces/SD/pages/8454145/Getting+Started+with+ZeroTier)

## Conclusion

Going with the third approach makes sense to me for the following reason: 

1. Less overhead on configuring the network. 
2. Security - my PC is connected to digital ocean within a private network. 

Are there other solutions other than the ones I could come up with? What are the limitations or flaws of my final solution? Any other tools I can use other than Zerotier?

Do let me know in the comments or drop a message on [LinkedIn](https://www.linkedin.com/in/rahultgeorge05)!