Crate relayport_rs

source ·
Expand description

Fast and easy abstraction for proxying TCP ports.

This library simplifies the creation of asynchronous TCP proxies from rust applications. The only limit on the number of proxies are the resources available on the system on which it is run. This library depends on tokio for its runtime.

Example

A simple program to proxy web traffic to a server might look like this:

use std::error::Error;
use tokio::sync::broadcast;
use relayport_rs::RelayTcpSocket;
use relayport_rs::command::RelayCommand;
use tokio::signal::unix::{signal, SignalKind};

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> {
    // The relay expects a broadcast channel on which to listen for shutdown commands
    let (tx, rx) = broadcast::channel(16);

    // build a relay with a listener TCP socket
    let relay = RelayTcpSocket::build()
        .set_so_reuseaddr(true)
        .set_tcp_nodelay(true)
        .bind("0.0.0.0:8080")?
        .listen()?;

    // spawn a task to handle the acceptance and dispatch of a relay connection
    let _ = tokio::task::spawn(async move {
        relay
            .run("127.0.0.1:80", &rx)
            .await
            .expect("failed to start relay")
    });


   // Wait for Ctrl-C to send the shutdown command
   let mut sigint = signal(SignalKind::interrupt())?;
   match sigint.recv().await {
       Some(()) => { tx.send(RelayCommand::Shutdown)?; {} },
       None => {},
   }

   Ok(())
}

This is the same program again, but we don’t care about catching a SIGINT:

use std::error::Error;
use tokio::sync::broadcast;
use relayport_rs::command::RelayCommand;
use relayport_rs::RelayPortError;
use relayport_rs::RelayTcpSocket;

#[tokio::main]
pub async fn main() -> Result<(), RelayPortError> {
    // The relay expects a broadcast channel on which to listen for shutdown commands
    let (tx, rx) = broadcast::channel(16);

    // build a relay with a listener TCP socket
    let relay = RelayTcpSocket::build()
        .set_so_reuseaddr(true)
        .set_tcp_nodelay(true)
        .bind("0.0.0.0:8080")?
        .listen()?;

    // spawn a task to handle the acceptance and dispatch of a relay connection
    relay
        .run("127.0.0.1:80", &rx)
        .await

}

This program relays UDP DNS transactions to CloudFlare’s DNS service:

use std::error::Error;
use tokio::sync::broadcast;
use relayport_rs::RelayUdpSocket;
use relayport_rs::command::RelayCommand;
use tokio::signal::unix::{signal, SignalKind};

#[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> {
    // The relay expects a broadcast channel on which to listen for shutdown commands
    let (tx, rx) = broadcast::channel(16);

    // build a relay with a listener TCP socket
    let relay = RelayUdpSocket::build()
        .set_so_reuseaddr(true)
        .bind("0.0.0.0:55353")
        .await?;

    // spawn a task to handle the acceptance and dispatch of a relay connection
    let _ = tokio::task::spawn(async move {
        relay
            .run("1.1.1.1:53", &rx)
            .await
            .expect("failed to start relay")
    });


   // Wait for Ctrl-C to send the shutdown command
   let mut sigint = signal(SignalKind::interrupt())?;
   match sigint.recv().await {
       Some(()) => { tx.send(RelayCommand::Shutdown)?; {} },
       None => {},
   }

   Ok(())
}

Re-exports

Modules

  • Command definitions
  • Errors returned by the library
  • Proxy TCP and UDP ports