sbd_server/config.rs
1#[cfg(feature = "unstable")]
2const DEF_IP_DENY_DIR: &str = ".";
3#[cfg(feature = "unstable")]
4const DEF_IP_DENY_S: i32 = 600;
5const DEF_LIMIT_CLIENTS: i32 = 32768;
6const DEF_LIMIT_IP_KBPS: i32 = 1000;
7const DEF_LIMIT_IP_BYTE_BURST: i32 = 16 * 16 * 1024;
8const DEF_LIMIT_IDLE_MILLIS: i32 = 10_000;
9
10/// Configure and execute an SBD server.
11#[derive(clap::Parser, Debug, Clone)]
12#[command(version, styles=get_styles())]
13pub struct Config {
14 /// TLS certificate path (pem).
15 /// If specified, `--priv-key-pem-file` must also be specified.
16 /// It is recommended to run acme service on port 80 and only
17 /// bind SBD to port 443.
18 #[arg(long)]
19 pub cert_pem_file: Option<std::path::PathBuf>,
20
21 /// TLS private key path (pem).
22 /// If specified, `--cert-pem-file` must also be specified.
23 /// It is recommended to run acme service on port 80 and only
24 /// bind SBD to port 443.
25 #[arg(long)]
26 pub priv_key_pem_file: Option<std::path::PathBuf>,
27
28 /// Bind to this interface and port. If multiple bindings specify port
29 /// zero, the server will attempt to bind the same port to each interface.
30 /// If it cannot, it will allow all the ports to be different.
31 /// Can be specified more than once.
32 /// E.g. `--bind 127.0.0.1:0 --bind [::1]:0 --bind 192.168.0.10:443`.
33 #[arg(long)]
34 pub bind: Vec<String>,
35
36 #[cfg(feature = "unstable")]
37 /// Watch this directory, and reload TLS certificates 10s after any
38 /// files change within it. Must be an exact match to the parent directory
39 /// of both `--cert-pem-file` and `--priv-key-pem-file`.
40 #[arg(long)]
41 pub watch_reload_tls_dir: Option<std::path::PathBuf>,
42
43 /// Use this http header to determine IP address instead of the raw
44 /// TCP connection details.
45 #[arg(long)]
46 pub trusted_ip_header: Option<String>,
47
48 #[cfg(feature = "unstable")]
49 /// The directory in which to store the blocked ip addresses.
50 /// Note v4 addresses will be mapped to v6 addresses per
51 /// <https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2>.
52 #[arg(long, default_value = DEF_IP_DENY_DIR)]
53 pub ip_deny_dir: std::path::PathBuf,
54
55 #[cfg(feature = "unstable")]
56 /// How long to block ip addresses in seconds. Set to zero to block
57 /// forever (or until the file is manually deleted).
58 #[arg(long, default_value_t = DEF_IP_DENY_S)]
59 pub ip_deny_s: i32,
60
61 #[cfg(feature = "unstable")]
62 /// Bind to this backchannel interface and port.
63 /// Can be specified more than once.
64 /// Note, this should be a local only or virtual private interface.
65 #[arg(long)]
66 pub back_bind: Vec<String>,
67
68 #[cfg(feature = "unstable")]
69 /// Allow incoming backchannel connections only
70 /// from the following explicit addresses. Note, this is expecting direct
71 /// connections, not through a proxy, so only the raw TCP address will
72 /// be validated. (This ignores the --trusted-ip-header parameter).
73 /// Can be specified more than once.
74 /// E.g. `--back-allow-ip 192.168.0.2 --back-allow-ip 192.168.0.3`.
75 #[arg(long)]
76 pub back_allow_ip: Vec<String>,
77
78 #[cfg(feature = "unstable")]
79 /// Try to establish outgoing backchannel connections
80 /// to the following ip+port addresses.
81 /// Can be specified more than once.
82 /// E.g. `--back-open 192.168.0.3:1443`
83 #[arg(long)]
84 pub back_open: Vec<String>,
85
86 #[cfg(feature = "unstable")]
87 /// Bind to this interface and port to provide prometheus metrics.
88 /// Note, this should be a local only or virtual private interface.
89 #[arg(long)]
90 pub bind_prometheus: Option<String>,
91
92 /// Limit client connections.
93 #[arg(long, default_value_t = DEF_LIMIT_CLIENTS)]
94 pub limit_clients: i32,
95
96 /// If set, rate-limiting will be disabled on the server,
97 /// and clients will be informed they have an 8gbps rate limit.
98 #[arg(long)]
99 pub disable_rate_limiting: bool,
100
101 /// Rate limit connections to this kilobits per second.
102 /// The default value of 1000 obviously limits connections to 1 mbps.
103 /// If the default of 32768 connections were all sending this amount
104 /// at the same time, the server would need a ~33 gbps connection.
105 /// The rate limit passed to clients will be divided by the number
106 /// of open connections for a given ip address.
107 #[arg(long, default_value_t = DEF_LIMIT_IP_KBPS)]
108 pub limit_ip_kbps: i32,
109
110 /// Allow IPs to burst by this byte count.
111 /// If the max message size is 16K, this value must be at least 16K.
112 /// The default value provides 16 * 16K to allow for multiple connections
113 /// from a single ip address sending full messages at the same time.
114 #[arg(long, default_value_t = DEF_LIMIT_IP_BYTE_BURST)]
115 pub limit_ip_byte_burst: i32,
116
117 /// How long in milliseconds connections can remain idle before being
118 /// closed. Clients must send either a message or a keepalive before
119 /// this time expires to keep the connection alive.
120 #[arg(long, default_value_t = DEF_LIMIT_IDLE_MILLIS)]
121 pub limit_idle_millis: i32,
122
123 /// The authentication "Hook Server" as defined by
124 /// <https://github.com/holochain/sbd/blob/main/spec-auth.md>
125 #[arg(long)]
126 pub authentication_hook_server: Option<String>,
127
128 /// If specified, this will enable exporting metrics to an OpenTelemetry endpoint.
129 #[arg(long)]
130 pub otlp_endpoint: Option<String>,
131}
132
133impl Default for Config {
134 /// Construct a new config with some defaults set.
135 fn default() -> Self {
136 Self {
137 cert_pem_file: None,
138 priv_key_pem_file: None,
139 bind: Vec::new(),
140 #[cfg(feature = "unstable")]
141 watch_reload_tls_dir: None,
142 trusted_ip_header: None,
143 #[cfg(feature = "unstable")]
144 ip_deny_dir: std::path::PathBuf::from(DEF_IP_DENY_DIR),
145 #[cfg(feature = "unstable")]
146 ip_deny_s: DEF_IP_DENY_S,
147 #[cfg(feature = "unstable")]
148 back_bind: Vec::new(),
149 #[cfg(feature = "unstable")]
150 back_allow_ip: Vec::new(),
151 #[cfg(feature = "unstable")]
152 back_open: Vec::new(),
153 #[cfg(feature = "unstable")]
154 bind_prometheus: None,
155 limit_clients: DEF_LIMIT_CLIENTS,
156 disable_rate_limiting: false,
157 limit_ip_kbps: DEF_LIMIT_IP_KBPS,
158 limit_ip_byte_burst: DEF_LIMIT_IP_BYTE_BURST,
159 limit_idle_millis: DEF_LIMIT_IDLE_MILLIS,
160 authentication_hook_server: None,
161 otlp_endpoint: None,
162 }
163 }
164}
165
166impl Config {
167 pub(crate) fn idle_dur(&self) -> std::time::Duration {
168 std::time::Duration::from_millis(self.limit_idle_millis as u64)
169 }
170
171 /// convert kbps into the nanosecond weight of each byte
172 /// (easier to rate limit with this value)
173 pub(crate) fn limit_ip_byte_nanos(&self) -> i32 {
174 8_000_000 / self.limit_ip_kbps
175 }
176}
177
178fn get_styles() -> clap::builder::Styles {
179 clap::builder::Styles::styled()
180 .usage(
181 anstyle::Style::new()
182 .bold()
183 .fg_color(Some(anstyle::Color::Ansi(
184 anstyle::AnsiColor::Yellow,
185 ))),
186 )
187 .header(
188 anstyle::Style::new()
189 .bold()
190 .fg_color(Some(anstyle::Color::Ansi(
191 anstyle::AnsiColor::Yellow,
192 ))),
193 )
194 .literal(
195 anstyle::Style::new().fg_color(Some(anstyle::Color::Ansi(
196 anstyle::AnsiColor::Green,
197 ))),
198 )
199 .invalid(
200 anstyle::Style::new()
201 .bold()
202 .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red))),
203 )
204 .error(
205 anstyle::Style::new()
206 .bold()
207 .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red))),
208 )
209 .valid(
210 anstyle::Style::new()
211 .bold()
212 .fg_color(Some(anstyle::Color::Ansi(
213 anstyle::AnsiColor::Green,
214 ))),
215 )
216 .placeholder(
217 anstyle::Style::new().fg_color(Some(anstyle::Color::Ansi(
218 anstyle::AnsiColor::White,
219 ))),
220 )
221}