Update README and minor refactor
This commit is contained in:
parent
0407f4b40c
commit
8a96de9666
27
README-EN.md
27
README-EN.md
@ -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
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user