Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set default tcp keepalive #116

Merged
merged 1 commit into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ PROXY OPTIONS:
TIMEOUT OPTIONS:
--tcp-timeout <second> override tcp timeout
--udp-timeout <second> override udp timeout
--tcp-keepalive <second> override default tcp keepalive interval(15s)

SUBCOMMANDS:
convert convert your legacy configuration into an advanced one
Expand Down Expand Up @@ -260,6 +261,7 @@ remote = "www.google.com:443"
├── network
│ ├── no_tcp
│ ├── use_udp
│ ├── tcp_keepalive
│ ├── tcp_timeout
│ ├── udp_timeout
│ ├── send_proxy
Expand Down Expand Up @@ -486,6 +488,14 @@ default: false

~~default: false~~

#### network.tcp_keepalive: unsigned int64

TCP Keepalive interval.

To use system tcp keepalive interval, you need to explicitly set timeout value to 0.

default: 15

#### network.tcp_timeout: unsigned int

This is **connect** timeout. An attempt to connect to a remote peer fails after waiting for a period of time.
Expand Down
1 change: 1 addition & 0 deletions realm_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pin-project = "1"
trust-dns-resolver = "0.22"
tokio = { version = "1.18", features = ["rt", "net", "time"] }
proxy-protocol = { version = "0.5", optional = true }
socket2 = "0.5.5"

[features]
default = []
Expand Down
6 changes: 4 additions & 2 deletions realm_core/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl ProxyOpts {
/// Connect or associate options.
#[derive(Debug, Default, Clone)]
pub struct ConnectOpts {
pub tcp_keepalive: u64,
pub connect_timeout: usize,
pub associate_timeout: usize,
pub bind_address: Option<SocketAddr>,
Expand Down Expand Up @@ -86,6 +87,7 @@ impl Display for Endpoint {
impl Display for ConnectOpts {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let ConnectOpts {
tcp_keepalive,
connect_timeout,
associate_timeout,
bind_address,
Expand Down Expand Up @@ -126,8 +128,8 @@ impl Display for ConnectOpts {

write!(
f,
"connect-timeout={}s, associate-timeout={}s; ",
connect_timeout, associate_timeout
"tcp-keepalive={}s connect-timeout={}s, associate-timeout={}s; ",
tcp_keepalive, connect_timeout, associate_timeout
)?;

#[cfg(feature = "transport")]
Expand Down
14 changes: 13 additions & 1 deletion realm_core/src/tcp/middle.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::io::Result;
use std::time::Duration;

use tokio::net::TcpStream;

Expand All @@ -16,7 +17,6 @@ use super::transport;

use crate::trick::Ref;
use crate::endpoint::{RemoteAddr, ConnectOpts};

#[allow(unused)]
pub async fn connect_and_relay(
mut local: TcpStream,
Expand All @@ -33,6 +33,8 @@ pub async fn connect_and_relay(

#[cfg(feature = "balance")]
balancer,

tcp_keepalive,
..
} = conn_opts.as_ref();

Expand Down Expand Up @@ -75,6 +77,16 @@ pub async fn connect_and_relay(

// connect!
let mut remote = socket::connect(raddr, conn_opts.as_ref()).await?;

if *tcp_keepalive > 0 {
let sockref = socket2::SockRef::from(&remote);
let mut ka = socket2::TcpKeepalive::new();

ka = ka
.with_time(Duration::from_secs(*tcp_keepalive))
.with_interval(Duration::from_secs(*tcp_keepalive));
let _ = sockref.set_tcp_keepalive(&ka);
}
log::info!("[tcp]{} => {} as {}", local.peer_addr()?, raddr, remote.peer_addr()?);

// after connected
Expand Down
9 changes: 9 additions & 0 deletions realm_core/src/tcp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod proxy;
mod transport;

use std::io::{ErrorKind, Result};
use std::time::Duration;

use crate::trick::Ref;
use crate::endpoint::Endpoint;
Expand Down Expand Up @@ -50,7 +51,15 @@ pub async fn run_tcp(endpoint: Endpoint) -> Result<()> {

// ignore error
let _ = local.set_nodelay(true);
if conn_opts.tcp_keepalive > 0 {
let sockref = socket2::SockRef::from(&local);
let mut ka = socket2::TcpKeepalive::new();
ka = ka
.with_time(Duration::from_secs(conn_opts.tcp_keepalive))
.with_interval(Duration::from_secs(conn_opts.tcp_keepalive));

let _ = sockref.set_tcp_keepalive(&ka);
}
tokio::spawn(async move {
match connect_and_relay(local, raddr, conn_opts, extra_raddrs).await {
Ok(..) => log::debug!("[tcp]{} => {}, finish", addr, raddr.as_ref()),
Expand Down
6 changes: 6 additions & 0 deletions src/cmd/flag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ pub fn add_global_options(app: Command) -> Command {
.value_name("second")
.takes_value(true)
.display_order(1),
Arg::new("tcp_keepalive")
.long("tcp-keepalive")
.help("override default tcp keepalive interval(15s)")
.value_name("second")
.takes_value(true)
.display_order(2),
]);

app
Expand Down
15 changes: 12 additions & 3 deletions src/conf/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{Serialize, Deserialize};
use realm_core::endpoint::{ConnectOpts, ProxyOpts};

use super::Config;
use crate::consts::{TCP_TIMEOUT, UDP_TIMEOUT};
use crate::consts::{TCP_KEEPALIVE, TCP_TIMEOUT, UDP_TIMEOUT};
use crate::consts::PROXY_PROTOCOL_VERSION;
use crate::consts::PROXY_PROTOCOL_TIMEOUT;

Expand Down Expand Up @@ -31,6 +31,10 @@ pub struct NetConf {
#[serde(default)]
pub accept_proxy_timeout: Option<usize>,

#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub tcp_keepalive: Option<u64>,

#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub tcp_timeout: Option<usize>,
Expand All @@ -53,7 +57,7 @@ impl Config for NetConf {
fn is_empty(&self) -> bool {
crate::empty![self =>
send_proxy, accept_proxy, send_proxy_version, accept_proxy_timeout,
tcp_timeout, udp_timeout
tcp_keepalive, tcp_timeout, udp_timeout
]
}

Expand All @@ -69,7 +73,7 @@ impl Config for NetConf {

let no_tcp = unbox!(no_tcp);
let use_udp = unbox!(use_udp);

let tcp_keepalive = unbox!(tcp_keepalive, TCP_KEEPALIVE);
let tcp_timeout = unbox!(tcp_timeout, TCP_TIMEOUT);
let udp_timeout = unbox!(udp_timeout, UDP_TIMEOUT);

Expand All @@ -80,6 +84,7 @@ impl Config for NetConf {
let accept_proxy_timeout = unbox!(accept_proxy_timeout, PROXY_PROTOCOL_TIMEOUT);

let conn_opts = ConnectOpts {
tcp_keepalive: tcp_keepalive,
connect_timeout: tcp_timeout,
associate_timeout: udp_timeout,

Expand Down Expand Up @@ -114,6 +119,7 @@ impl Config for NetConf {

rst!(self, no_tcp, other);
rst!(self, use_udp, other);
rst!(self, tcp_keepalive, other);
rst!(self, tcp_timeout, other);
rst!(self, udp_timeout, other);
rst!(self, send_proxy, other);
Expand All @@ -129,6 +135,7 @@ impl Config for NetConf {

take!(self, no_tcp, other);
take!(self, use_udp, other);
take!(self, tcp_keepalive, other);
take!(self, tcp_timeout, other);
take!(self, udp_timeout, other);
take!(self, send_proxy, other);
Expand All @@ -155,6 +162,7 @@ impl Config for NetConf {
let no_tcp = unpack!("no_tcp");
let use_udp = unpack!("use_udp");

let tcp_keepalive = unpack!("tcp_keepalive", u64);
let tcp_timeout = unpack!("tcp_timeout", usize);
let udp_timeout = unpack!("udp_timeout", usize);

Expand All @@ -167,6 +175,7 @@ impl Config for NetConf {
Self {
no_tcp,
use_udp,
tcp_keepalive,
tcp_timeout,
udp_timeout,
send_proxy,
Expand Down
1 change: 1 addition & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fmt::{Display, Formatter};
pub const DEFAULT_LOG_FILE: &str = "stdout";

// default timeout
pub const TCP_KEEPALIVE: u64 = 15;
pub const TCP_TIMEOUT: usize = 5;
pub const UDP_TIMEOUT: usize = 30;

Expand Down