Skip to content

Commit

Permalink
Add TLS support for http (#39)
Browse files Browse the repository at this point in the history
* add TLS support on backends

Signed-off-by: andrewmatilde <[email protected]>

* support TLS

Signed-off-by: andrewmatilde <[email protected]>

* fix connect

Signed-off-by: andrewmatilde <[email protected]>

* fix tls config

Signed-off-by: andrewmatilde <[email protected]>

* fix client

Signed-off-by: andrewmatilde <[email protected]>

* fix client scheme

Signed-off-by: andrewmatilde <[email protected]>

* fix client authority

Signed-off-by: andrewmatilde <[email protected]>

* fix connector

Signed-off-by: andrewmatilde <[email protected]>

* delete some unnecessary code

Signed-off-by: andrewmatilde <[email protected]>

* fix-lock

Signed-off-by: andrewmatilde <[email protected]>

* try fix loop select

Signed-off-by: andrewmatilde <[email protected]>

* fmt

Signed-off-by: andrewmatilde <[email protected]>

* use span

Signed-off-by: andrewmatilde <[email protected]>

* fix BUG

Signed-off-by: andrewmatilde <[email protected]>

* fix duplicate code.

Signed-off-by: andrewmatilde <[email protected]>

* fix all

Signed-off-by: andrewmatilde <[email protected]>
  • Loading branch information
Andrewmatilde authored May 30, 2022
1 parent adb39a1 commit a7c97cd
Show file tree
Hide file tree
Showing 15 changed files with 823 additions and 336 deletions.
746 changes: 522 additions & 224 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ members = ["chaos-tproxy-controller", "chaos-tproxy-proxy", "tests"]
anyhow = "1.0"
clap = "2.33.3"
futures = "0.3.10"
http = "0.2.3"
http = "0.2.7"
humantime-serde = "1.0"
hyper = {git = "https://github.com/Andrewmatilde/hyper.git", features = ["runtime", "client", "server", "http1", "http2", "stream", "error_return"]}
iptables = "0.4"
Expand All @@ -44,6 +44,12 @@ bincode = "1.3.3"
default-net = "0.9.0"
system_gateway = {git="https://github.com/aruntomar/system_gateway"}
base64 = "0.13.0"
tokio-rustls = "0.23.4"
rustls = "0.20.4"
derivative = "2.2.0"
rustls-pemfile = "1.0.0"
webpki-roots = "0.22"
hyper-rustls = { git = "https://github.com/Andrewmatilde/hyper-rustls.git", features = ["http2"] }
rtnetlink = "0.9.1"
iproute2-rs = {git="https://github.com/chaos-mesh/iproute2-rs.git"}
futures-util = "0.3"
Expand Down
12 changes: 9 additions & 3 deletions chaos-tproxy-controller/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ path = "src/lib.rs"
anyhow = "1.0"
clap = "2.33.3"
futures = "0.3.10"
http = "0.2.3"
http = "0.2.7"
humantime-serde = "1.0"
hyper = {version = "0.14.4", features = ["runtime", "client", "server", "http1", "http2", "stream"]}
hyper = {git = "https://github.com/Andrewmatilde/hyper.git", features = ["runtime", "client", "server", "http1", "http2", "stream", "error_return"]}
iptables = "0.4"
libc = {version = "0.2.81", features = ["std"]}
paw = "1.0"
Expand Down Expand Up @@ -45,4 +45,10 @@ pnet = "0.28.0"
default-net = "0.9.0"
rtnetlink = "0.9.1"
iproute2-rs = {git="https://github.com/chaos-mesh/iproute2-rs.git"}
system_gateway = {git="https://github.com/aruntomar/system_gateway"}
system_gateway = {git="https://github.com/aruntomar/system_gateway"}
tokio-rustls = "0.23.4"
rustls = "0.20.4"
derivative = "2.2.0"
rustls-pemfile = "1.0.0"
webpki-roots = "0.22"
hyper-rustls = { git = "https://github.com/Andrewmatilde/hyper-rustls.git", features = ["http2"] }
9 changes: 7 additions & 2 deletions chaos-tproxy-controller/src/proxy/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ impl TryFrom<RawConfig> for Config {
Some(rules) => rules,
None => vec![],
},
tls: raw.tls,
},
})
}
Expand Down Expand Up @@ -76,6 +77,7 @@ mod tests {
safe_mode: None,
interface: None,
rules: None,
tls: None,

listen_port: None,
proxy_mark: None,
Expand All @@ -92,7 +94,8 @@ mod tests {
listen_port: get_free_port(None).unwrap(),
safe_mode: false,
interface: None,
rules: vec![]
rules: vec![],
tls: None
}
}
);
Expand All @@ -102,6 +105,7 @@ mod tests {
safe_mode: Some(true),
interface: Some("ens33".parse().unwrap()),
rules: None,
tls: None,

listen_port: None,
proxy_mark: None,
Expand All @@ -118,7 +122,8 @@ mod tests {
listen_port: 1027u16,
safe_mode: true,
interface: Some("ens33".parse().unwrap()),
rules: vec![]
rules: vec![],
tls: None
}
}
);
Expand Down
2 changes: 1 addition & 1 deletion chaos-tproxy-controller/src/proxy/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::path::PathBuf;
use std::process::Stdio;

use anyhow::Error;
use rtnetlink::{Handle, new_connection};
use chaos_tproxy_proxy::raw_config::RawConfig as ProxyRawConfig;
use rtnetlink::{new_connection, Handle};
use tokio::process::Command;
use tokio::select;
use tokio::sync::oneshot::{channel, Receiver, Sender};
Expand Down
26 changes: 13 additions & 13 deletions chaos-tproxy-controller/src/proxy/net/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use default_net;
use default_net::Gateway;
use pnet::datalink::NetworkInterface;
use pnet::ipnetwork::{IpNetwork, Ipv4Network};
use rtnetlink::Handle;
use rtnetlink::packet::route::Nla;
use rtnetlink::packet::RouteMessage;
use rtnetlink::Handle;
use uuid::Uuid;
use crate::proxy::net::iptables::clear_ebtables;

use crate::proxy::net::iptables::clear_ebtables;
use crate::proxy::net::routes::{del_routes_noblock, get_routes_noblock, load_routes};

#[derive(Debug, Clone)]
Expand All @@ -31,7 +31,7 @@ pub struct NetEnv {
}

impl NetEnv {
pub async fn new(handle:&Handle) -> Self {
pub async fn new(handle: &Handle) -> Self {
let interfaces = pnet::datalink::interfaces();
let prefix = loop {
let key = Uuid::new_v4().to_string()[0..13].to_string();
Expand Down Expand Up @@ -194,12 +194,10 @@ impl NetEnv {
.mac
.context(format!("mac {} not found", self.veth4.clone()))?
.to_string();
execute_all(vec![
ip_netns(
&self.netns,
arp_set(&net.ip().to_string(), &veth4_mac, &self.bridge2),
),
])?;
execute_all(vec![ip_netns(
&self.netns,
arp_set(&net.ip().to_string(), &veth4_mac, &self.bridge2),
)])?;

let all_routes = get_routes_noblock(handle).await?;

Expand All @@ -226,7 +224,7 @@ impl NetEnv {
Ok(())
}

pub async fn clear_bridge(&self, handle:&mut Handle) -> Result<()> {
pub async fn clear_bridge(&self, handle: &mut Handle) -> Result<()> {
let restore_dns = "cp /etc/resolv.conf.bak /etc/resolv.conf";

let cmdvv = vec![
Expand All @@ -243,9 +241,11 @@ impl NetEnv {
vec![]
});

del_routes_noblock(handle, routes).await.unwrap_or_else(|e| {
tracing::error!("clear routes del_routes_noblock with error {}", e);
});
del_routes_noblock(handle, routes)
.await
.unwrap_or_else(|e| {
tracing::error!("clear routes del_routes_noblock with error {}", e);
});

load_routes(handle, self.save_routes.clone())
.await
Expand Down
4 changes: 2 additions & 2 deletions chaos-tproxy-controller/src/proxy/net/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use anyhow::{anyhow, Result};
use futures_util::future::join_all;
use iproute2_rs::ip::iproute::{del_routes, get_routes, Action, IPRoute};
use rtnetlink::packet::RouteMessage;
use rtnetlink::{IpVersion, Handle};

use rtnetlink::{Handle, IpVersion};

pub async fn get_routes_noblock(handle: &Handle) -> Result<Vec<RouteMessage>> {
let routes = get_routes(handle, IpVersion::V4).await?;
Expand Down Expand Up @@ -45,6 +44,7 @@ pub async fn load_routes(handle: &mut Handle, msgs: Vec<RouteMessage>) -> Result
mod test {
use rtnetlink::new_connection;
use tokio::spawn;

use crate::proxy::net::routes::{del_routes_noblock, get_routes_noblock, load_routes};

#[ignore]
Expand Down
1 change: 1 addition & 0 deletions chaos-tproxy-controller/src/proxy/net/set_net.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::option::Option::Some;

use rtnetlink::Handle;

use crate::proxy::net::bridge::{bash_c, execute, execute_all, get_interface, NetEnv};
Expand Down
3 changes: 2 additions & 1 deletion chaos-tproxy-controller/src/raw_config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use chaos_tproxy_proxy::raw_config::RawRule;
use chaos_tproxy_proxy::raw_config::{RawRule, TLSRawConfig};
use serde::{Deserialize, Serialize};

#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Default)]
Expand All @@ -8,6 +8,7 @@ pub struct RawConfig {
pub safe_mode: Option<bool>,
pub interface: Option<String>,
pub rules: Option<Vec<RawRule>>,
pub tls: Option<TLSRawConfig>,

// Useless options now. Keep these options for upward compatible.
pub listen_port: Option<u16>,
Expand Down
8 changes: 7 additions & 1 deletion chaos-tproxy-proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ edition = "2018"
anyhow = "1.0"
clap = "2.33.3"
futures = "0.3.10"
http = "0.2.3"
http = "0.2.7"
humantime-serde = "1.0"
hyper = {git = "https://github.com/Andrewmatilde/hyper.git", features = ["runtime", "client", "server", "http1", "http2", "stream", "error_return"]}
iptables = "0.4"
Expand All @@ -34,5 +34,11 @@ bincode = "1.3.3"
tempfile = "3.2.0"
uuid = { version = "0.8", features = ["serde", "v4"] }
base64 = "0.13.0"
tokio-rustls = "0.23.4"
rustls = "0.20.4"
derivative = "2.2.0"
rustls-pemfile = "1.0.0"
webpki-roots = "0.22"
hyper-rustls = { git = "https://github.com/Andrewmatilde/hyper-rustls.git", features = ["http2"] }
rtnetlink = "0.9.1"
futures-util = "0.3"
16 changes: 15 additions & 1 deletion chaos-tproxy-proxy/src/proxy/http/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
use rustls::{ClientConfig, ServerConfig};

use crate::handler::http::rule::Rule;

#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct Config {
pub http_config: HTTPConfig,
pub tls_config: Option<TLSConfig>,
}

#[derive(Clone, Debug)]
pub struct HTTPConfig {
pub proxy_port: u16,
pub rules: Vec<Rule>,
}

#[derive(Clone)]
pub struct TLSConfig {
pub tls_client_config: ClientConfig,
pub tls_server_config: ServerConfig,
}
42 changes: 6 additions & 36 deletions chaos-tproxy-proxy/src/proxy/http/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ use std::net::SocketAddr;
use std::pin::Pin;
use std::task::{Context, Poll};

use anyhow::{anyhow, Error, Result};
use http::uri::Scheme;
use anyhow::{Error, Result};
use http::Uri;
use hyper::client::connect::dns::GaiResolver;
use hyper::service::Service;
use tokio::net::TcpStream;
use tracing::{instrument, trace};
Expand All @@ -15,22 +13,20 @@ use crate::proxy::tcp::transparent_socket::TransparentSocket;

#[derive(Debug, Clone)]
pub struct HttpConnector {
resolver: GaiResolver,
target: SocketAddr,
socket: TransparentSocket,
}

impl HttpConnector {
pub fn new(src: SocketAddr) -> Self {
pub fn new(dst: SocketAddr, src: SocketAddr) -> Self {
Self {
resolver: GaiResolver::new(),
target: dst,
socket: TransparentSocket::new(src),
}
}

async fn connect(mut self, dist: Uri) -> Result<TcpStream> {
let addr = resolve(&mut self.resolver, &dist).await?;
trace!("resolved addr({})", dist);
Ok(self.socket.conn(addr).await?)
async fn connect(self, _: Uri) -> Result<TcpStream> {
Ok(self.socket.conn(self.target).await?)
}
}

Expand All @@ -43,7 +39,6 @@ impl Service<Uri> for HttpConnector {

#[instrument]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
futures::ready!(self.resolver.poll_ready(cx))?;
trace!("connector is ready");
Poll::Ready(Ok(()))
}
Expand All @@ -53,28 +48,3 @@ impl Service<Uri> for HttpConnector {
Box::pin(self.clone().connect(dst))
}
}

/// This function resolve uri and select uri with scheme like `http://`
/// and get host addrs and dst port from Uri.
pub(crate) async fn resolve(resolver: &mut GaiResolver, dst: &Uri) -> Result<SocketAddr, Error> {
if dst
.scheme()
.filter(|scheme| **scheme != Scheme::HTTP)
.is_some()
{
return Err(anyhow!("https connector cannot handle http request"));
}

let host = dst
.host()
.ok_or_else(|| anyhow!("target uri has no host"))?;
let mut addrs = resolver.call(host.parse()?).await?;
let mut addr = addrs
.next()
.ok_or_else(|| anyhow!("cannot resolve {}", host))?;

if let Some(port) = dst.port() {
addr.set_port(port.as_u16());
}
Ok(addr)
}
Loading

0 comments on commit a7c97cd

Please sign in to comment.