Giter Site home page Giter Site logo

shadesmar's Introduction

Contributors Forks Stargazers Issues MIT License


Logo

shadesmar

A userspace networking stack for virtual machines
Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Getting Started
  3. Quickstart
  4. Configuration
  5. Usage
  6. Contributing
  7. License

About The Project

shadesmar is a userspace networking stack with support for Qemu virtual machines via the vhost-user protocol. It includes a layer 2 switch, layer 3 router, and a few different WAN connection types (WireGuard, blackhole, udp, tap). It supports logging traffic, a dynamic routing table and WANs, split-WAN configurations, and includes a basic DHCPv4 server to simplify virtual machine setup.

(back to top)

Getting Started

If you plan to build from source, shadesmar is built using Rust. See the prerequisites section for how to install it before continuing.

Prerequisites

  • Rust / Cargo 1.75+
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Installation

  1. Clone the repo

    git clone https://github.com/kvnallsn/shadesmar.git
  2. Build the executables

    cargo build --release
  3. Create the required directories and ensure user has access

    sudo mkdir -p /etc/shadesmar
    sudo mkdir -p /var/lib/shadesmar
    sudo mkdir -p /var/run/shadesmar
    
    sudo chown $USER /etc/shadesmar
    sudo chown $USER /var/lib/shadesmar
    sudo chown $USER /var/run/shadesmar

Note

The executable (shadesmar) will be located in the target/release folder.

(back to top)

Quickstart

Important

Ensure you have the qemu-system-x86 package installed on your system. Otherwise the virtual machine will not run. The shadesmar executable must also be in your path.

Setup

Download shadesmar and move it into a directory in your $PATH and ensure all required directories exist and are writable by your current user

$ wget https://github.com/kvnallsn/shadesmar/releases/download/v0.0.1/shadesmar
$ chmod +x shadesmar
$ sudo mv shadesmar /usr/local/bin/shadesmar

$ sudo mkdir -p /etc/shadesmar
$ sudo mkdir -p /var/lib/shadesmar
$ sudo mkdir -p /var/run/shadesmar

$ sudo chown $USER /etc/shadesmar
$ sudo chown $USER /var/lib/shadesmar
$ sudo chown $USER /var/run/shadesmar

Download the orion.tgz archive, extract it, and enter the orion directory in three separate terminals.

$ wget https://github.com/kvnallsn/shadesmar/raw/main/examples/orion.tgz
$ tar zxf orion.tgz
$ cd orion

Important

From this point on, all terminals should be in the orion directory.

Terminal A: Install and Start the Network

The following two commands will install a new network, start it, and wait for VMs to connect.

$ shadesmar install ./orion.yml
$ shadesmar net orion start 

Terminal B: Connect a Qemu Virtual Machine

The following script will start an Alpine Linux virtual machine with Qemu, connect to the shadesmar network backend, and spawn a TTY on stdin (ttyS0 / serial)

$ ./run.sh

After the virtual machine has started, login with root. It should not prompt for a password, as one is not set. You can now interact with the virtual machine as you would any other virtual machine.

The example has a blackhole WAN adapter configured as the default (and only) route, any network traffic generated will be dropped. However, the pcap option is configured, so all network traffic the adapter receives will captured in a pcap file at /var/lib/shadesmar/orion/pcap/wan-blackhole-<timestamp>.pcap.

Terminal C: Explore Shadesmar Commands

In the third terminal, you can explore the various commands shadesmar offers.

Watch Packets on the Switch

Using the netflow command, you can watch traffic cross the switch in real time.

In Termainl C:

$ shadesmar net orion netflow

In Terminal B:

Run any command that will generate network traffic, for example: ping

$ ping -c 4 1.1.1.1

You should see something similiar to following output in Terminal C:

| ------------------------------ | ---------- | ----------- | ------------------------------------------------------------ |
|           Date/Time            |  Protocol  |    Size     |                           Details                            |
| ------------------------------ | ---------- | ----------- | ------------------------------------------------------------ |
| 2024-08-16T22:55:06.078560507Z | arp        |    28 bytes | who has 10.67.213.1? tell 10.67.213.150                      |
| 2024-08-16T22:55:06.078749065Z | arp        |    28 bytes | 10.67.213.1 is at 52:54:00:47:40:83                          |
| 2024-08-16T22:55:06.079322153Z | ipv4/icmp  |    84 bytes | [echo request] 10.67.213.150 --> 1.1.1.1                     |
| 2024-08-16T22:55:07.078603163Z | ipv4/icmp  |    84 bytes | [echo request] 10.67.213.150 --> 1.1.1.1                     |
| 2024-08-16T22:55:08.078568152Z | ipv4/icmp  |    84 bytes | [echo request] 10.67.213.150 --> 1.1.1.1                     |
| 2024-08-16T22:55:09.079032128Z | ipv4/icmp  |    84 bytes | [echo request] 10.67.213.150 --> 1.1.1.1                     |

Note

Remember, only the blackhole adapter is configured, so you should not see any echo replies~

(back to top)

Qemu Configuration

For a qemu virtual machine to use the network, the host must be able to access guest memory (memory-backend-memfd/numa) and a vhost-user chardev/netdev/device must be specified.

The following shows an example of the minimum flags that must be specified to interface with a shadesmar network named orion:

qemu-system-x86_64 \
    - <...> \    # all other flags (-M, -enable-kvm, -m, etc.)
    -object memory-backend-memfd,id=mem,size=512m,share=on \  # size must match -m flag
    -numa node,memdev=mem \                                   
    -chardev socket,id=chr0,path=/var/run/shadesmar/orion/vhost.sock \
    -netdev type=vhost-user,id=net0,chardev=chr0,queues=1 \
    -device virtio-net-pci,netdev=net0,mac=00:56:50,de:ad:00

(back to top)

Network Configuration

shadesmar is configured using a YAML file to specify the network's settings (such as router subnet and DHCP).

The network supports an optional WAN configuration that will be used to forward all non-local traffic (aka traffic not destined for other devices in the subnet). The following WAN providers exist or under development:

Type Config Key Status Description
Blackhole blackhole functioning Logs (via PCAP) and drops all traffic
WireGuard wireguard functioning Encrypts and forwards traffic to a WireGuard endpoint
UDP udp functioning Forwards all traffic to the specified UDP endpoint
TAP Device tap under development Exposes traffic to host device/network

Below is a sample configuration for a router serving the 10.67.213.0/24 subnet:

  • Wan section explaination:

    • Create a blackhole device that will drop all traffic it receives
    • Create a WireGuard device with the specified parameters
  • Router section explaination:

    • Set to IPv4 address + subnet of the router to 10.67.213.1/24
    • Enable DHCP server, with an address range of 10.67.213.100 - 10.67.213.200
    • Disable internal DNS server (not implemented yet)
    • Configure the routing table
      • Drop any traffic without an explicit route (i.e., the default route is a blackhole device)
      • Route traffic to 1.1.1.1/32 over the "dns-route" wan device
wan:
  - name: blackhole
    pcap: true
    device:
        type: blackhole
  - name: dns-route
    pcap: false
    device:
        type: wireguard
        key: ---secret key goes here---
        peer: ---peer public key here---
        endpoint: ---endpoint socket address here---
        ipv4: ---assigned ipv4 address for private key---

router:
    ipv4: 10.67.213.1/24
    dhcp:
     start: 10.67.213.100
      end: 10.67.213.200
    dns: false
    table:
        0.0.0.0/0: blackhole    # default route
        1.1.1.1/32: dns-route

(back to top)

Usage

shadesmar creates a new userspace networking stack. Qemu virtual machines can connect through the vhost-user socket for individual networks. Below are some sample commands to execute various different tasks.

Install / Create a Network

shadesmar install ./path/to/config.yml

Installs a network configuration into the net config directory (default: /var/lib/shadesmar/<network>/).

By default, the network name will be taken from the name of the configuration file. For example, a installing the config orion.yml would create a new network named orion. The name can be manually specified using the -n flag.

Start a Network

shadesmar net <network> start

After a network has been installed, it can be started. Starting a network runs in the foreground. Daemonization has not been added/supported yet.

Stop a Network

shadesmar net <network> stop

A network may be stopped in a few different ways:

  • Use the shadesmar cli to issue a stop command
  • Sending a SIGINT (ctrl-c) or SIGTERM signal to the process id

It is recommended to ensure all connected virtual machines have been stopped/disconnected before stopping a network. Stopping a network which still has conencted virtual machines is undefined behavior.

Check Network Status

shadesmar net <network> status

The status command will print the status of the router, WAN interfaces, current routing table, and switch port status of a network.

Example output:

$ shadesmar status orion
Router Status:
MAC:      52:54:00:2b:89:7b
Network:  10.10.10.1/24

WAN Interfaces:
┌──────────────────────────────────────────────────────────────────────────────┐
│        Name        │  Status  │     Type     │      TX       │      RX       │
├──────────────────────────────────────────────────────────────────────────────┤
│ new-jersey         │ running  │ WireGuard    │           0 B │           0 B │
│ san-jose           │ running  │ WireGuard    │         644 B │         336 B │
└──────────────────────────────────────────────────────────────────────────────┘

Route Table:
┌──────────────────────────────────────────────────────────────────────────────┐
│     Destination      │         Via          │          Packet Count          │
├──────────────────────────────────────────────────────────────────────────────┤
│ default              │ new-jersey           │ 0                              │
│ 1.1.1.1/32           │ san-jose             │ 4                              │
└──────────────────────────────────────────────────────────────────────────────┘

Switch Status:
┌──────────────────────────────────────────────────────────────────────────────┐
│   Port   │    Type    │                         MACs                         │
├──────────────────────────────────────────────────────────────────────────────┤
│        0 │ router     │ 52:54:00:2b:89:7b                                    │
│        1 │ virtio     │ 00:56:50:de:ad:00                                    │
└──────────────────────────────────────────────────────────────────────────────┘

Examine traffic

shadesmar net <network> netflow

Prints traffic crossing the switch to stdout in a table format.

Example output:

| ------------------------------ | ---------- | ----------- | ------------------------------------------------------------ |
|           Date/Time            |  Protocol  |    Size     |                           Details                            |
| ------------------------------ | ---------- | ----------- | ------------------------------------------------------------ |
| 2024-08-16T19:40:09.247570137Z | ipv4/udp   |   328 bytes | 0.0.0.0:68 --> 255.255.255.255:67                            |
| 2024-08-16T19:40:09.247919404Z | ipv4/udp   |   308 bytes | 255.255.255.255:67 --> 0.0.0.0:68                            |
| 2024-08-16T19:40:09.248738349Z | ipv4/udp   |   328 bytes | 0.0.0.0:68 --> 255.255.255.255:67                            |
| 2024-08-16T19:40:09.24904596Z  | ipv4/udp   |   308 bytes | 255.255.255.255:67 --> 0.0.0.0:68                            |
| 2024-08-16T19:40:19.805040673Z | arp        |    28 bytes | who has 10.10.10.1? tell 10.10.10.100                        |
| 2024-08-16T19:40:19.805266919Z | arp        |    28 bytes | 10.10.10.1 is at 52:54:00:07:f8:0a                           |
| 2024-08-16T19:40:19.805783103Z | ipv4/icmp  |    84 bytes | [echo request] 10.10.10.100 --> 1.1.1.1                      |

Add a route

shadesmar net <network> route add <cidr> <wan-device>

Adds a new route to the routing table, ensuring all future traffic will travese the stated wan device. If the route already exists, it will be updated to use the newly-specified device.

Delete a route

shadesmar net <network> route delete <cidr>

Removes a route from the routing table. Any future traffic to this cidr will use the default route (i.e., 0.0.0.0/32)

Add a WAN device

shadesmar net <network> wan add <path/to/wan/cfg.yml>

Adds a new WAN device that may be used to route traffic. The yaml file must contain all required parameters for the type of wan device being created.

Delete a WAN device

shadesmar net <network> wan delete <wan>

Stops and deletes a WAN device. If the WAN device has active routes in the routing table, all traffic will be dropped. Alternatively, the -a/--clean option may be specified to remove all associated routes with the WAN device. In this case, all traffic will fallback to the default route.

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

shadesmar's People

Contributors

kvnallsn avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.