Skip to content

Commit ed872f1

Browse files
committed
Option to not log back requests to the client
Closes #7
1 parent 79c199f commit ed872f1

13 files changed

+110
-12
lines changed

src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub struct ApplicationConfig {
3838
pub http_port: u16,
3939
pub https_port: u16,
4040
pub force_https: bool,
41+
pub disable_http_logs: bool,
42+
pub disable_tcp_logs: bool,
4143
pub acme_contact_email: Option<String>,
4244
pub acme_use_staging: bool,
4345
pub password_authentication_url: Option<String>,

src/http.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ const X_FORWARDED_PROTO: &str = "X-Forwarded-Proto";
2929
const X_FORWARDED_PORT: &str = "X-Forwarded-Port";
3030

3131
fn http_log(
32+
ip: &str,
3233
status: u16,
3334
method: &str,
3435
host: &str,
3536
uri: &str,
3637
elapsed_time: Duration,
3738
tx: Option<mpsc::UnboundedSender<Vec<u8>>>,
39+
disable_http_logs: bool,
3840
) {
3941
let status_escape_color = match status {
4042
100..=199 => "37m",
@@ -57,18 +59,21 @@ fn http_log(
5759
_ => "44m",
5860
};
5961
let line = format!(
60-
" \x1b[2m{:19}\x1b[22m \x1b[{}[{:3}] \x1b[0;1;{}{:^7}\x1b[0m {} => {} \x1b[2m{}\x1b[0m\r\n",
62+
" \x1b[2m{:19}\x1b[22m \x1b[{}[{:3}] \x1b[0;1;{}{:^7}\x1b[0m {} => {} \x1b[2m({}) {}\x1b[0m\r\n",
6163
chrono::Local::now().format("%Y-%m-%dT%H:%M:%S"),
6264
status_escape_color,
6365
status,
6466
method_escape_color,
6567
method,
6668
host,
6769
uri,
70+
ip,
6871
pretty_duration::pretty_duration(&elapsed_time, None)
6972
);
7073
print!("{}", line);
71-
let _ = tx.map(|tx| tx.send(line.into_bytes()));
74+
if !disable_http_logs {
75+
let _ = tx.map(|tx| tx.send(line.into_bytes()));
76+
}
7277
}
7378

7479
pub(crate) enum Protocol {
@@ -98,6 +103,7 @@ pub(crate) async fn proxy_handler<B, H, T, R>(
98103
protocol: Protocol,
99104
http_request_timeout: Duration,
100105
websocket_timeout: Option<Duration>,
106+
disable_http_logs: bool,
101107
) -> anyhow::Result<Response<AxumBody>>
102108
where
103109
H: ConnectionHandler<T>,
@@ -117,16 +123,19 @@ where
117123
.next()
118124
.ok_or(ServerError::InvalidHostHeader)?
119125
.to_owned();
126+
let ip = tcp_address.ip().to_canonical().to_string();
120127
let Some(handler) = conn_manager.get(&host) else {
121128
if domain_redirect.from == host {
122129
let elapsed = timer.elapsed();
123130
http_log(
131+
&ip,
124132
StatusCode::SEE_OTHER.as_u16(),
125133
request.method().as_str(),
126134
&host,
127135
request.uri().path(),
128136
elapsed,
129137
None,
138+
disable_http_logs,
130139
);
131140
return Ok(Redirect::to(&domain_redirect.to).into_response());
132141
}
@@ -153,12 +162,14 @@ where
153162
)
154163
.into_response();
155164
http_log(
165+
&ip,
156166
response.status().as_u16(),
157167
request.method().as_str(),
158168
&host,
159169
request.uri().path(),
160170
elapsed,
161171
None,
172+
disable_http_logs,
162173
);
163174
return Ok(response);
164175
}
@@ -167,7 +178,6 @@ where
167178
Protocol::Https { port } => ("https", port.to_string()),
168179
Protocol::TlsRedirect { .. } => unreachable!(),
169180
};
170-
let ip = tcp_address.ip().to_string();
171181
request
172182
.headers_mut()
173183
.insert(X_FORWARDED_FOR, ip.parse().unwrap());
@@ -204,12 +214,14 @@ where
204214
.map_err(|_| ServerError::RequestTimeout)??;
205215
let elapsed = timer.elapsed();
206216
http_log(
217+
&ip,
207218
response.status().as_u16(),
208219
&method,
209220
&host,
210221
&uri,
211222
elapsed,
212223
Some(tx),
224+
disable_http_logs,
213225
);
214226
Ok(response.into_response())
215227
}
@@ -227,12 +239,14 @@ where
227239
.map_err(|_| ServerError::RequestTimeout)??;
228240
let elapsed = timer.elapsed();
229241
http_log(
242+
&ip,
230243
response.status().as_u16(),
231244
&method,
232245
&host,
233246
&uri,
234247
elapsed,
235248
Some(tx),
249+
disable_http_logs,
236250
);
237251
match response.status() {
238252
StatusCode::SWITCHING_PROTOCOLS => {
@@ -321,6 +335,7 @@ mod proxy_handler_tests {
321335
Protocol::Http { port: 80 },
322336
Duration::from_secs(5),
323337
None,
338+
false,
324339
)
325340
.await;
326341
assert!(response.is_err());
@@ -352,6 +367,7 @@ mod proxy_handler_tests {
352367
Protocol::Http { port: 80 },
353368
Duration::from_secs(5),
354369
None,
370+
false,
355371
)
356372
.await;
357373
assert!(response.is_ok());
@@ -385,6 +401,7 @@ mod proxy_handler_tests {
385401
Protocol::Http { port: 80 },
386402
Duration::from_secs(5),
387403
None,
404+
false,
388405
)
389406
.await;
390407
assert!(response.is_ok());
@@ -432,6 +449,7 @@ mod proxy_handler_tests {
432449
Protocol::TlsRedirect { from: 80, to: 443 },
433450
Duration::from_secs(5),
434451
None,
452+
false,
435453
)
436454
.await;
437455
assert!(response.is_ok());
@@ -479,6 +497,7 @@ mod proxy_handler_tests {
479497
Protocol::TlsRedirect { from: 80, to: 8443 },
480498
Duration::from_secs(5),
481499
None,
500+
false,
482501
)
483502
.await;
484503
assert!(response.is_ok());
@@ -555,6 +574,7 @@ mod proxy_handler_tests {
555574
Protocol::Https { port: 443 },
556575
Duration::from_secs(5),
557576
None,
577+
false,
558578
)
559579
.await;
560580
assert!(!logging_rx.is_empty());
@@ -632,6 +652,7 @@ mod proxy_handler_tests {
632652
Protocol::Https { port: 443 },
633653
Duration::from_secs(5),
634654
None,
655+
false,
635656
)
636657
.await;
637658
assert!(!logging_rx.is_empty());
@@ -703,6 +724,7 @@ mod proxy_handler_tests {
703724
Protocol::Https { port: 443 },
704725
Duration::from_secs(5),
705726
None,
727+
false,
706728
)
707729
});
708730
let jh2 = tokio::spawn(async move {

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ pub async fn entrypoint(config: ApplicationConfig) -> anyhow::Result<()> {
164164
config.listen_address.clone(),
165165
Arc::clone(&tcp_connections),
166166
config.tcp_connection_timeout,
167+
config.disable_tcp_logs,
167168
));
168169
tcp_connections.update_reactor(Some(Arc::clone(&tcp_handler)));
169170
let addressing = Arc::new(AddressDelegator::new(
@@ -208,6 +209,7 @@ pub async fn entrypoint(config: ApplicationConfig) -> anyhow::Result<()> {
208209
},
209210
config.http_request_timeout,
210211
config.tcp_connection_timeout,
212+
config.disable_http_logs,
211213
)
212214
});
213215
let io = TokioIo::new(stream);
@@ -248,6 +250,7 @@ pub async fn entrypoint(config: ApplicationConfig) -> anyhow::Result<()> {
248250
},
249251
config.http_request_timeout,
250252
config.tcp_connection_timeout,
253+
config.disable_http_logs,
251254
)
252255
});
253256
match LazyConfigAcceptor::new(Default::default(), stream).await {

src/main.rs

+10
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ struct Args {
140140
#[arg(long, default_value_t = false)]
141141
force_https: bool,
142142

143+
/// Disable sending HTTP logs to clients.
144+
#[arg(long, default_value_t = false)]
145+
disable_http_logs: bool,
146+
147+
/// Disable sending TCP/proxy logs to clients.
148+
#[arg(long, default_value_t = false)]
149+
disable_tcp_logs: bool,
150+
143151
/// Contact e-mail to use with Let's Encrypt. If set, enables ACME for HTTPS certificates.
144152
///
145153
/// By providing your e-mail, you agree to Let's Encrypt Subscriber Agreement.
@@ -235,6 +243,8 @@ async fn main() -> anyhow::Result<()> {
235243
http_port: args.http_port,
236244
https_port: args.https_port,
237245
force_https: args.force_https,
246+
disable_http_logs: args.disable_http_logs,
247+
disable_tcp_logs: args.disable_tcp_logs,
238248
acme_contact_email: args.acme_contact_email,
239249
acme_use_staging: args.acme_use_staging,
240250
password_authentication_url: args.password_authentication_url,

src/ssh.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
borrow::Borrow,
23
collections::{HashMap, HashSet},
34
fmt::Display,
45
net::SocketAddr,
@@ -91,7 +92,7 @@ struct UserData {
9192
http_hosts: HashSet<String>,
9293
tcp_aliases: HashSet<TcpAlias>,
9394
host_addressing: HashMap<(String, u32), String>,
94-
port_addressing: HashMap<(String, u32), u16>,
95+
port_addressing: HashMap<(String, u32), TcpAlias>,
9596
}
9697

9798
impl Default for UserData {
@@ -597,11 +598,16 @@ impl Handler for ServerHandler {
597598
} else {
598599
*port as u16
599600
};
601+
let tcp_alias = if is_alias(address) {
602+
address
603+
} else {
604+
"localhost"
605+
};
600606
if self
601607
.server
602608
.tcp
603609
.insert(
604-
TcpAlias(address.to_string(), assigned_port),
610+
TcpAlias(tcp_alias.to_string(), assigned_port),
605611
self.peer,
606612
Arc::new(SshTunnelHandler::new(
607613
Arc::clone(&user_data.allow_fingerprint),
@@ -616,10 +622,11 @@ impl Handler for ServerHandler {
616622
{
617623
user_data
618624
.tcp_aliases
619-
.insert(TcpAlias(address.to_string(), assigned_port));
620-
user_data
621-
.port_addressing
622-
.insert((address.to_string(), *port), assigned_port);
625+
.insert(TcpAlias(tcp_alias.to_string(), assigned_port));
626+
user_data.port_addressing.insert(
627+
(address.to_string(), *port),
628+
TcpAlias(tcp_alias.to_string(), assigned_port),
629+
);
623630
if is_alias(address) {
624631
info!(
625632
"Tunneling TCP port {} for alias {} ({})",
@@ -718,11 +725,11 @@ impl Handler for ServerHandler {
718725
}
719726
}
720727
_ => {
721-
if let Some(assigned_port) = user_data
728+
if let Some(assigned_alias) = user_data
722729
.port_addressing
723730
.remove(&(address.to_string(), port))
724731
{
725-
let key: &dyn TcpAliasKey = &BorrowedTcpAlias(address, &assigned_port);
732+
let key: &dyn TcpAliasKey = assigned_alias.borrow();
726733
self.server.tcp.remove(key, self.peer);
727734
user_data.tcp_aliases.remove(key);
728735
Ok(true)
@@ -757,6 +764,13 @@ impl Handler for ServerHandler {
757764
self.auth_data = AuthenticatedData::Proxy;
758765
*self.is_proxied.lock().await = true;
759766
}
767+
let _ = handler.log_channel().send(
768+
format!(
769+
"New HTTP proxy from {}:{} => http://{}",
770+
originator_address, originator_port, host_to_connect
771+
)
772+
.into_bytes(),
773+
);
760774
tokio::spawn(async move {
761775
let mut stream = channel.into_stream();
762776
let _ = copy_bidirectional(&mut stream, &mut io).await;
@@ -785,6 +799,13 @@ impl Handler for ServerHandler {
785799
self.auth_data = AuthenticatedData::Proxy;
786800
*self.is_proxied.lock().await = true;
787801
}
802+
let _ = handler.log_channel().send(
803+
format!(
804+
"New SSH proxy from {}:{} => {}:{}",
805+
originator_address, originator_port, host_to_connect, port_to_connect
806+
)
807+
.into_bytes(),
808+
);
788809
tokio::spawn(async move {
789810
let mut stream = channel.into_stream();
790811
let _ = copy_bidirectional(&mut stream, &mut io).await;
@@ -816,6 +837,13 @@ impl Handler for ServerHandler {
816837
self.auth_data = AuthenticatedData::Proxy;
817838
*self.is_proxied.lock().await = true;
818839
}
840+
let _ = handler.log_channel().send(
841+
format!(
842+
"New TCP proxy from {}:{} => {}:{}",
843+
originator_address, originator_port, host_to_connect, port_to_connect
844+
)
845+
.into_bytes(),
846+
);
819847
tokio::spawn(async move {
820848
let mut stream = channel.into_stream();
821849
let _ = copy_bidirectional(&mut stream, &mut io).await;

0 commit comments

Comments
 (0)