Update README and minor refactor

This commit is contained in:
KernelErr 2021-11-01 15:25:12 +08:00
parent 0407f4b40c
commit 8a96de9666
3 changed files with 40 additions and 39 deletions

View File

@ -33,34 +33,31 @@ $ cargo install fourth
## Configuration ## Configuration
Fourth will read yaml format configuration file from `/etc/fourth/config.yaml`, here is an example: Fourth will read yaml format configuration file from `/etc/fourth/config.yaml`, here is an minimal viable example:
```yaml ```yaml
version: 1 version: 1
log: info log: info
servers: servers:
example_server: proxy_server:
listen:
- "0.0.0.0:443"
- "[::]:443"
tls: true # Enable TLS features like SNI
sni:
proxy.example.com: proxy
www.example.com: nginx
default: ban
relay_server:
listen: listen:
- "127.0.0.1:8081" - "127.0.0.1:8081"
default: remote default: remote
upstream: upstream:
nginx: "127.0.0.1:8080" remote: "tcp://www.remote.example.com:8082" # proxy to remote address
proxy: "127.0.0.1:1024"
remote: "www.remote.example.com:8082" # proxy to remote address
``` ```
Built-in two upstreams: ban(terminate connection immediately), echo Built-in two upstreams: ban(terminate connection immediately), echo. For detailed configuration, check [this example](./example-config.yaml).
## Performance Benchmark
Tested on 4C2G server:
Use fourth to proxy to Nginx(QPS of direct connection: ~120000): ~70000 req/s (Command: `wrk -t200 -c1000 -d120s --latency http://proxy-server:8081`)
Use fourth to proxy to local iperf3: 8Gbps
## Thanks ## Thanks

View File

@ -67,31 +67,33 @@ async fn process(
match upstream { match upstream {
Upstream::Ban => { Upstream::Ban => {
let _ = inbound.shutdown(); let _ = inbound.shutdown();
Ok(())
} }
Upstream::Echo => { Upstream::Echo => {
let (mut ri, mut wi) = io::split(inbound); let (mut ri, mut wi) = io::split(inbound);
let inbound_to_inbound = copy(&mut ri, &mut wi); let inbound_to_inbound = copy(&mut ri, &mut wi);
let bytes_tx = inbound_to_inbound.await; let bytes_tx = inbound_to_inbound.await;
debug!("Bytes read: {:?}", bytes_tx); debug!("Bytes read: {:?}", bytes_tx);
Ok(())
} }
Upstream::Custom(custom) => { Upstream::Custom(custom) => {
let outbound = TcpStream::connect(custom.addr.clone()).await?; match custom.protocol.as_ref() {
"tcp" => {
let outbound = TcpStream::connect(custom.addr.clone()).await?;
let (mut ri, mut wi) = io::split(inbound); let (mut ri, mut wi) = io::split(inbound);
let (mut ro, mut wo) = io::split(outbound); let (mut ro, mut wo) = io::split(outbound);
let inbound_to_outbound = copy(&mut ri, &mut wo); let inbound_to_outbound = copy(&mut ri, &mut wo);
let outbound_to_inbound = copy(&mut ro, &mut wi); let outbound_to_inbound = copy(&mut ro, &mut wi);
let (bytes_tx, bytes_rx) = try_join(inbound_to_outbound, outbound_to_inbound).await?; let (bytes_tx, bytes_rx) = try_join(inbound_to_outbound, outbound_to_inbound).await?;
debug!("Bytes read: {:?} write: {:?}", bytes_tx, bytes_rx); debug!("Bytes read: {:?} write: {:?}", bytes_tx, bytes_rx);
}
Ok(()) _ => {}
}
} }
} };
Ok(())
} }
async fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> io::Result<u64> async fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> io::Result<u64>

View File

@ -86,31 +86,33 @@ async fn process(
match upstream { match upstream {
Upstream::Ban => { Upstream::Ban => {
let _ = inbound.shutdown(); let _ = inbound.shutdown();
Ok(())
} }
Upstream::Echo => { Upstream::Echo => {
let (mut ri, mut wi) = io::split(inbound); let (mut ri, mut wi) = io::split(inbound);
let inbound_to_inbound = copy(&mut ri, &mut wi); let inbound_to_inbound = copy(&mut ri, &mut wi);
let bytes_tx = inbound_to_inbound.await; let bytes_tx = inbound_to_inbound.await;
debug!("Bytes read: {:?}", bytes_tx); debug!("Bytes read: {:?}", bytes_tx);
Ok(())
} }
Upstream::Custom(custom) => { Upstream::Custom(custom) => {
let outbound = TcpStream::connect(custom.addr.clone()).await?; match custom.protocol.as_ref() {
"tcp" => {
let outbound = TcpStream::connect(custom.addr.clone()).await?;
let (mut ri, mut wi) = io::split(inbound); let (mut ri, mut wi) = io::split(inbound);
let (mut ro, mut wo) = io::split(outbound); let (mut ro, mut wo) = io::split(outbound);
let inbound_to_outbound = copy(&mut ri, &mut wo); let inbound_to_outbound = copy(&mut ri, &mut wo);
let outbound_to_inbound = copy(&mut ro, &mut wi); let outbound_to_inbound = copy(&mut ro, &mut wi);
let (bytes_tx, bytes_rx) = try_join(inbound_to_outbound, outbound_to_inbound).await?; let (bytes_tx, bytes_rx) = try_join(inbound_to_outbound, outbound_to_inbound).await?;
debug!("Bytes read: {:?} write: {:?}", bytes_tx, bytes_rx); debug!("Bytes read: {:?} write: {:?}", bytes_tx, bytes_rx);
}
Ok(()) _ => {}
}
} }
} };
Ok(())
} }
async fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> io::Result<u64> async fn copy<'a, R, W>(reader: &'a mut R, writer: &'a mut W) -> io::Result<u64>