1use std::{
13 cell::RefCell,
14 collections::{BTreeMap, HashMap, hash_map::Entry},
15 io::ErrorKind,
16 net::{Shutdown, SocketAddr as StdSocketAddr},
17 os::unix::io::AsRawFd,
18 rc::{Rc, Weak},
19 str::{from_utf8, from_utf8_unchecked},
20 sync::Arc,
21 time::{Duration, Instant},
22};
23
24use mio::{
25 Interest, Registry, Token,
26 net::{TcpListener as MioTcpListener, TcpStream as MioTcpStream},
27 unix::SourceFd,
28};
29use rustls::{
30 CipherSuite, ProtocolVersion, ServerConfig as RustlsServerConfig, ServerConnection,
31 SupportedCipherSuite, crypto::CryptoProvider,
32};
33use rusty_ulid::Ulid;
34use sozu_command::{
35 certificate::Fingerprint,
36 config::{DEFAULT_ALPN_PROTOCOLS, DEFAULT_CIPHER_LIST},
37 proto::command::{
38 AddCertificate, CertificateSummary, CertificatesByAddress, Cluster, HttpsListenerConfig,
39 ListOfCertificatesByAddress, ListenerType, RemoveCertificate, RemoveListener,
40 ReplaceCertificate, RequestHttpFrontend, ResponseContent, TlsVersion,
41 UpdateHttpsListenerConfig, WorkerRequest, WorkerResponse, request::RequestType,
42 response_content::ContentType,
43 },
44 ready::Ready,
45 response::HttpFrontend,
46 state::{
47 ClusterId, validate_alpn_protocols, validate_h2_flood_knobs_https, validate_sozu_id_header,
48 },
49};
50
51use crate::metrics::names;
52use crate::{
53 AcceptError, CachedTags, FrontendFromRequestError, L7ListenerHandler, L7Proxy, ListenerError,
54 ListenerHandler, Protocol, ProxyConfiguration, ProxyError, ProxySession, SessionIsToBeClosed,
55 SessionMetrics, SessionResult, StateMachineBuilder, StateResult,
56 backends::BackendMap,
57 crypto::{cipher_suite_by_name, default_provider, kx_group_by_name},
58 pool::Pool,
59 protocol::{
60 Pipe, SessionState,
61 http::answers::HttpAnswers,
62 http::parser::{Method, hostname_and_port},
63 mux::{self, Mux, MuxTls},
64 proxy_protocol::expect::ExpectProxyProtocol,
65 rustls::TlsHandshake,
66 },
67 router::{RouteResult, Router},
68 server::{ListenToken, SessionManager},
69 socket::{FrontRustls, server_bind},
70 timer::TimeoutContainer,
71 tls::MutexCertificateResolver,
72 util::UnwrapLog,
73};
74
75StateMachineBuilder! {
76 enum HttpsStateMachine impl SessionState {
83 Expect(ExpectProxyProtocol<MioTcpStream>, ServerConnection),
84 Handshake(TlsHandshake),
85 Mux(MuxTls),
86 WebSocket(Pipe<FrontRustls, HttpsListener>),
87 }
88}
89
90enum AlpnProtocol {
91 H2,
92 Http11,
93}
94
95macro_rules! log_module_context {
102 () => {{
103 let (open, reset, _, _, _) = sozu_command::logging::ansi_palette();
104 format!("{open}HTTPS{reset}\t >>>", open = open, reset = reset)
105 }};
106}
107
108macro_rules! log_context {
114 ($self:expr) => {{
115 let (open, reset, grey, gray, white) = sozu_command::logging::ansi_palette();
116 format!(
117 "{open}HTTPS{reset}\t{grey}Session{reset}({gray}frontend{reset}={white}{frontend}{reset}, {gray}peer{reset}={white}{peer}{reset})\t >>>",
118 open = open,
119 reset = reset,
120 grey = grey,
121 gray = gray,
122 white = white,
123 frontend = $self.frontend_token.0,
124 peer = $self.peer_address.map(|a| a.to_string()).unwrap_or_else(|| "<none>".to_string()),
125 )
126 }};
127}
128
129pub struct HttpsSession {
130 configured_backend_timeout: Duration,
131 configured_connect_timeout: Duration,
132 configured_frontend_timeout: Duration,
133 frontend_token: Token,
134 has_been_closed: bool,
135 last_event: Instant,
136 listener: Rc<RefCell<HttpsListener>>,
137 metrics: SessionMetrics,
138 peer_address: Option<StdSocketAddr>,
139 pool: Weak<RefCell<Pool>>,
140 proxy: Rc<RefCell<HttpsProxy>>,
141 public_address: StdSocketAddr,
142 state: HttpsStateMachine,
143}
144
145impl HttpsSession {
146 #[allow(clippy::too_many_arguments)]
147 pub fn new(
148 configured_backend_timeout: Duration,
149 configured_connect_timeout: Duration,
150 configured_frontend_timeout: Duration,
151 configured_request_timeout: Duration,
152 expect_proxy: bool,
153 listener: Rc<RefCell<HttpsListener>>,
154 pool: Weak<RefCell<Pool>>,
155 proxy: Rc<RefCell<HttpsProxy>>,
156 public_address: StdSocketAddr,
157 rustls_details: ServerConnection,
158 sock: MioTcpStream,
159 token: Token,
160 wait_time: Duration,
161 ) -> HttpsSession {
162 let peer_address = if expect_proxy {
163 None
165 } else {
166 sock.peer_addr().ok()
167 };
168
169 let request_id = Ulid::generate();
170 let container_frontend_timeout = TimeoutContainer::new(configured_request_timeout, token);
171
172 let state = if expect_proxy {
173 trace!("{} starting in expect proxy state", log_module_context!());
174 gauge_add!(names::protocol::PROXY_EXPECT, 1);
175 HttpsStateMachine::Expect(
176 ExpectProxyProtocol::new(container_frontend_timeout, sock, token, request_id),
177 rustls_details,
178 )
179 } else {
180 gauge_add!(names::protocol::TLS_HANDSHAKE, 1);
181 HttpsStateMachine::Handshake(TlsHandshake::new(
182 container_frontend_timeout,
183 rustls_details,
184 sock,
185 token,
186 request_id,
187 peer_address,
188 ))
189 };
190
191 let metrics = SessionMetrics::new(Some(wait_time));
192 HttpsSession {
193 configured_backend_timeout,
194 configured_connect_timeout,
195 configured_frontend_timeout,
196 frontend_token: token,
197 has_been_closed: false,
198 last_event: Instant::now(),
199 listener,
200 metrics,
201 peer_address,
202 pool,
203 proxy,
204 public_address,
205 state,
206 }
207 }
208
209 pub fn upgrade(&mut self) -> SessionIsToBeClosed {
210 debug!("{} upgrade", log_context!(self));
211 let new_state = match self.state.take() {
212 HttpsStateMachine::Expect(expect, ssl) => self.upgrade_expect(expect, ssl),
213 HttpsStateMachine::Handshake(handshake) => self.upgrade_handshake(handshake),
214 HttpsStateMachine::Mux(mux) => self.upgrade_mux(mux),
215 HttpsStateMachine::WebSocket(wss) => self.upgrade_websocket(wss),
216 HttpsStateMachine::FailedUpgrade(_) => {
217 error!(
221 "{} upgrade called on FailedUpgrade state; closing session",
222 log_context!(self)
223 );
224 None
225 }
226 };
227
228 match new_state {
229 Some(state) => {
230 self.state = state;
231 false
232 }
233 None => true,
235 }
236 }
237
238 fn upgrade_expect(
239 &mut self,
240 mut expect: ExpectProxyProtocol<MioTcpStream>,
241 ssl: ServerConnection,
242 ) -> Option<HttpsStateMachine> {
243 if let Some(ref addresses) = expect.addresses {
244 if let (Some(public_address), Some(session_address)) =
245 (addresses.destination(), addresses.source())
246 {
247 self.public_address = public_address;
248 self.peer_address = Some(session_address);
249
250 let ExpectProxyProtocol {
251 container_frontend_timeout,
252 frontend,
253 frontend_readiness: readiness,
254 request_id,
255 ..
256 } = expect;
257
258 let mut handshake = TlsHandshake::new(
259 container_frontend_timeout,
260 ssl,
261 frontend,
262 self.frontend_token,
263 request_id,
264 self.peer_address,
265 );
266 handshake.frontend_readiness = readiness;
269 handshake.frontend_readiness.event.insert(Ready::READABLE);
270
271 gauge_add!(names::protocol::PROXY_EXPECT, -1);
272 gauge_add!(names::protocol::TLS_HANDSHAKE, 1);
273 return Some(HttpsStateMachine::Handshake(handshake));
274 }
275 }
276
277 if !expect.container_frontend_timeout.cancel() {
279 error!(
280 "{} failed to cancel request timeout on expect upgrade phase for 'expect proxy protocol with AF_UNSPEC address'",
281 log_context!(self)
282 );
283 }
284
285 None
286 }
287
288 fn upgrade_handshake(&mut self, handshake: TlsHandshake) -> Option<HttpsStateMachine> {
289 let sni_owned: Option<String> = handshake
301 .session
302 .server_name()
303 .map(|s| s.to_ascii_lowercase())
304 .map(|mut s| {
305 if s.ends_with('.') {
306 s.pop();
307 }
308 s
309 });
310 let alpn = handshake.session.alpn_protocol();
311 let alpn = alpn.and_then(|alpn| from_utf8(alpn).ok());
312 debug!(
313 "{} successful TLS handshake with, received: {:?} {:?}",
314 log_context!(self),
315 sni_owned,
316 alpn
317 );
318
319 let disable_http11 = self.listener.borrow().is_http11_disabled();
324 let (alpn, alpn_label): (AlpnProtocol, Option<&'static str>) = match alpn {
329 Some("http/1.1") => {
330 if disable_http11 {
331 incr!(names::https::ALPN_REJECTED_HTTP11_DISABLED);
332 warn!(
333 "{} rejecting TLS connection: listener is H2-only but client negotiated http/1.1",
334 log_context!(self)
335 );
336 return None;
337 }
338 (AlpnProtocol::Http11, Some("http/1.1"))
339 }
340 Some("h2") => (AlpnProtocol::H2, Some("h2")),
341 Some(other) => {
342 incr!(names::https::ALPN_REJECTED_UNSUPPORTED);
349 error!(
350 "{} unsupported ALPN protocol: {}",
351 log_context!(self),
352 other
353 );
354 return None;
355 }
356 None => {
360 if disable_http11 {
361 incr!(names::https::ALPN_REJECTED_HTTP11_DISABLED);
362 warn!(
363 "{} rejecting TLS connection: listener is H2-only but client did not negotiate ALPN",
364 log_context!(self)
365 );
366 return None;
367 }
368 (AlpnProtocol::Http11, None)
369 }
370 };
371
372 let tls_version_label = handshake
377 .session
378 .protocol_version()
379 .and_then(rustls_version_label);
380 let tls_cipher_label = handshake
381 .session
382 .negotiated_cipher_suite()
383 .and_then(rustls_ciphersuite_label);
384 if let Some(version) = handshake.session.protocol_version() {
385 incr!(rustls_version_str(version));
386 };
387 if let Some(cipher) = handshake.session.negotiated_cipher_suite() {
388 incr!(rustls_ciphersuite_str(cipher));
389 };
390
391 gauge_add!(names::protocol::TLS_HANDSHAKE, -1);
392
393 let session_ulid = rusty_ulid::Ulid::generate();
394 let front_stream = FrontRustls {
395 stream: handshake.stream,
396 session: handshake.session,
397 peer_disconnected: false,
398 peer_reset: false,
399 session_ulid,
400 };
401 let router = mux::Router::new(
402 self.configured_backend_timeout,
403 self.configured_connect_timeout,
404 );
405 let mut context = mux::Context::new(
406 session_ulid,
407 self.pool.clone(),
408 self.listener.clone(),
409 self.peer_address,
410 self.public_address,
411 );
412 let tls_cert_names: Option<Arc<Vec<String>>> = match sni_owned.as_deref() {
467 Some(sni) => self
468 .listener
469 .borrow()
470 .resolver()
471 .names_for_sni(sni.as_bytes())
472 .and_then(|names| {
473 let mut snapshot: Vec<String> = names
474 .into_iter()
475 .map(|mut name| {
476 name.make_ascii_lowercase();
477 if name.ends_with('.') {
478 name.pop();
479 }
480 name
481 })
482 .collect();
483 snapshot.sort();
484 snapshot.dedup();
485 if snapshot.is_empty() {
486 None
487 } else {
488 Some(Arc::new(snapshot))
489 }
490 }),
491 None => None,
492 };
493 context.tls_server_name = sni_owned;
497 context.tls_cert_names = tls_cert_names;
498 context.tls_version = tls_version_label;
502 context.tls_cipher = tls_cipher_label;
503 context.tls_alpn = alpn_label;
504 let mut frontend = match alpn {
505 AlpnProtocol::Http11 => {
506 incr!(names::http::ALPN_HTTP11);
507 context.create_stream(handshake.request_id, 1 << 16)?;
508 mux::Connection::new_h1_server(
509 session_ulid,
510 front_stream,
511 handshake.container_frontend_timeout,
512 )
513 }
514 AlpnProtocol::H2 => {
515 incr!(names::http::ALPN_H2);
516 let flood_config = self.listener.borrow().get_h2_flood_config();
517 let connection_config = self.listener.borrow().get_h2_connection_config();
518 let stream_idle_timeout = self.listener.borrow().get_h2_stream_idle_timeout();
519 let graceful_shutdown_deadline =
520 self.listener.borrow().get_h2_graceful_shutdown_deadline();
521 mux::Connection::new_h2_server(
522 session_ulid,
523 front_stream,
524 self.pool.clone(),
525 handshake.container_frontend_timeout,
526 flood_config,
527 connection_config,
528 stream_idle_timeout,
529 graceful_shutdown_deadline,
530 )?
531 }
532 };
533 frontend
542 .readiness_mut()
543 .event
544 .insert(Ready::READABLE | Ready::WRITABLE);
545
546 gauge_add!(names::protocol::HTTPS, 1);
547 Some(HttpsStateMachine::Mux(Mux {
548 configured_frontend_timeout: self.configured_frontend_timeout,
549 frontend_token: self.frontend_token,
550 frontend,
551 context,
552 router,
553 session_ulid,
554 }))
555 }
556
557 fn upgrade_mux(&self, mut mux: MuxTls) -> Option<HttpsStateMachine> {
558 debug!("{} mux switching to wss", log_context!(self));
559 let Some(stream) = mux.context.streams.pop() else {
560 error!(
561 "{} upgrade_mux: no stream attached to the TLS mux session, closing",
562 log_context!(self)
563 );
564 return None;
565 };
566 let (frontend_readiness, frontend_socket, mut container_frontend_timeout) =
570 match mux.frontend {
571 mux::Connection::H1(mux::ConnectionH1 {
572 readiness,
573 socket,
574 timeout_container,
575 ..
576 }) => (readiness, socket, timeout_container),
577 mux::Connection::H2(_) => {
578 error!(
579 "{} only h1<->h1 connections can upgrade to websocket",
580 log_context!(self)
581 );
582 return None;
583 }
584 };
585
586 let mux::StreamState::Linked(back_token) = stream.state else {
587 error!(
588 "{} upgrading stream should be linked to a backend",
589 log_context!(self)
590 );
591 return None;
592 };
593 let Some(backend) = mux.router.backends.remove(&back_token) else {
594 error!(
595 "{} upgrade_mux: backend for token {:?} is missing (already disconnected?), closing",
596 log_context!(self),
597 back_token
598 );
599 return None;
600 };
601 let (cluster_id, backend, backend_readiness, backend_socket, mut container_backend_timeout) =
602 match backend {
603 mux::Connection::H1(mux::ConnectionH1 {
604 position:
605 mux::Position::Client(cluster_id, backend, mux::BackendStatus::Connected),
606 readiness,
607 socket,
608 timeout_container,
609 ..
610 }) => (cluster_id, backend, readiness, socket, timeout_container),
611 mux::Connection::H1(_) => {
612 error!(
613 "{} the backend disconnected just after upgrade, abort",
614 log_context!(self)
615 );
616 return None;
617 }
618 mux::Connection::H2(_) => {
619 error!(
620 "{} only h1<->h1 connections can upgrade to websocket",
621 log_context!(self)
622 );
623 return None;
624 }
625 };
626
627 let ws_context = stream.context.websocket_context();
628
629 container_frontend_timeout.reset();
630 container_backend_timeout.reset();
631
632 let backend_id = backend.borrow().backend_id.clone();
633 let backend_socket = backend_socket.stream;
636 let mut pipe = Pipe::new(
637 stream.back.storage.buffer,
638 Some(backend_id),
639 Some(backend_socket),
640 Some(backend),
641 Some(container_backend_timeout),
642 Some(container_frontend_timeout),
643 Some(cluster_id),
644 stream.front.storage.buffer,
645 self.frontend_token,
646 frontend_socket,
647 self.listener.clone(),
648 Protocol::HTTPS,
649 stream.context.session_id,
650 stream.context.id,
651 stream.context.session_address,
652 ws_context,
653 );
654
655 pipe.frontend_readiness.event = frontend_readiness.event;
656 pipe.backend_readiness.event = backend_readiness.event;
657 pipe.set_back_token(back_token);
658 pipe.set_tls_metadata(
664 stream.context.tls_version,
665 stream.context.tls_cipher,
666 stream.context.tls_server_name.clone(),
667 stream.context.tls_alpn,
668 );
669
670 gauge_add!(names::protocol::HTTPS, -1);
673 gauge_add!(names::protocol::WSS, 1);
674 gauge_add!(names::websocket::ACTIVE_REQUESTS, 1);
675 Some(HttpsStateMachine::WebSocket(pipe))
676 }
677
678 fn upgrade_websocket(
679 &self,
680 wss: Pipe<FrontRustls, HttpsListener>,
681 ) -> Option<HttpsStateMachine> {
682 error!(
684 "{} upgrade called on WSS, this should not happen",
685 log_context!(self)
686 );
687 Some(HttpsStateMachine::WebSocket(wss))
688 }
689}
690
691impl ProxySession for HttpsSession {
692 fn close(&mut self) {
693 if self.has_been_closed {
694 return;
695 }
696
697 trace!("{} closing HTTPS session", log_context!(self));
698 self.metrics.service_stop();
699
700 match self.state.marker() {
702 StateMarker::Expect => gauge_add!(names::protocol::PROXY_EXPECT, -1),
703 StateMarker::Handshake => gauge_add!(names::protocol::TLS_HANDSHAKE, -1),
704 StateMarker::Mux => gauge_add!(names::protocol::HTTPS, -1),
705 StateMarker::WebSocket => {
706 gauge_add!(names::protocol::WSS, -1);
707 gauge_add!(names::websocket::ACTIVE_REQUESTS, -1);
708 }
709 }
710
711 if self.state.failed() {
712 match self.state.marker() {
713 StateMarker::Expect => incr!(names::https::UPGRADE_EXPECT_FAILED),
714 StateMarker::Handshake => incr!(names::https::UPGRADE_HANDSHAKE_FAILED),
715 StateMarker::Mux => incr!(names::https::UPGRADE_MUX_FAILED),
716 StateMarker::WebSocket => incr!(names::https::UPGRADE_WSS_FAILED),
717 }
718 self.state.close(self.proxy.clone(), &mut self.metrics);
722 self.proxy.borrow().remove_session(self.frontend_token);
723 self.has_been_closed = true;
724 return;
725 }
726
727 self.state.cancel_timeouts();
728 self.state.close(self.proxy.clone(), &mut self.metrics);
731
732 let front_socket = self.state.front_socket();
739 if let Err(e) = front_socket.shutdown(Shutdown::Write) {
740 if e.kind() != ErrorKind::NotConnected {
742 error!(
743 "{} error shutting down front socket({:?}): {:?}",
744 log_context!(self),
745 front_socket,
746 e
747 );
748 }
749 }
750
751 let proxy = self.proxy.borrow();
753 let fd = front_socket.as_raw_fd();
754 if let Err(e) = proxy.registry.deregister(&mut SourceFd(&fd)) {
755 error!(
756 "{} error deregistering front socket({:?}) while closing HTTPS session: {:?}",
757 log_context!(self),
758 fd,
759 e
760 );
761 }
762 proxy.remove_session(self.frontend_token);
763
764 self.has_been_closed = true;
765 }
766
767 fn timeout(&mut self, token: Token) -> SessionIsToBeClosed {
768 let session_result = self.state.timeout(token, &mut self.metrics);
769 if session_result == StateResult::CloseSession {
770 debug!(
771 "{} HTTPS timeout requested close: token={:?}, marker={:?}",
772 log_context!(self),
773 token,
774 self.state.marker()
775 );
776 }
777 session_result == StateResult::CloseSession
778 }
779
780 fn protocol(&self) -> Protocol {
781 Protocol::HTTPS
782 }
783
784 fn update_readiness(&mut self, token: Token, events: Ready) {
785 trace!(
786 "{} token {:?} got event {}",
787 log_context!(self),
788 token,
789 super::ready_to_string(events)
790 );
791 self.last_event = Instant::now();
792 self.metrics.wait_start();
793 self.state.update_readiness(token, events);
794 }
795
796 fn ready(&mut self, session: Rc<RefCell<dyn ProxySession>>) -> SessionIsToBeClosed {
797 self.metrics.service_start();
798
799 let session_result =
800 self.state
801 .ready(session.clone(), self.proxy.clone(), &mut self.metrics);
802
803 let to_be_closed = match session_result {
804 SessionResult::Close => true,
805 SessionResult::Continue => false,
806 SessionResult::Upgrade => match self.upgrade() {
807 false => self.ready(session),
808 true => true,
809 },
810 };
811 if to_be_closed {
812 debug!(
813 "{} HTTPS ready requested close: marker={:?}",
814 log_context!(self),
815 self.state.marker()
816 );
817 }
818
819 self.metrics.service_stop();
820 to_be_closed
821 }
822
823 fn shutting_down(&mut self) -> SessionIsToBeClosed {
824 self.state.shutting_down()
825 }
826
827 fn last_event(&self) -> Instant {
828 self.last_event
829 }
830
831 fn print_session(&self) {
832 self.state.print_state("HTTPS");
833 error!("{} Metrics: {:?}", log_context!(self), self.metrics);
834 }
835
836 fn frontend_token(&self) -> Token {
837 self.frontend_token
838 }
839}
840
841pub type HostName = String;
842pub type PathBegin = String;
843
844pub struct HttpsListener {
845 active: bool,
846 address: StdSocketAddr,
847 answers: Rc<RefCell<HttpAnswers>>,
848 config: HttpsListenerConfig,
849 fronts: Router,
850 listener: Option<MioTcpListener>,
851 resolver: Arc<MutexCertificateResolver>,
852 rustls_details: Arc<RustlsServerConfig>,
853 tags: BTreeMap<String, CachedTags>,
854 token: Token,
855}
856
857impl ListenerHandler for HttpsListener {
858 fn get_addr(&self) -> &StdSocketAddr {
859 &self.address
860 }
861
862 fn get_tags(&self, key: &str) -> Option<&CachedTags> {
863 self.tags.get(key)
864 }
865
866 fn set_tags(&mut self, key: String, tags: Option<BTreeMap<String, String>>) {
867 match tags {
868 Some(tags) => self.tags.insert(key, CachedTags::new(tags)),
869 None => self.tags.remove(&key),
870 };
871 }
872
873 fn protocol(&self) -> Protocol {
874 Protocol::HTTPS
875 }
876
877 fn public_address(&self) -> StdSocketAddr {
878 self.config
879 .public_address
880 .map(|addr| addr.into())
881 .unwrap_or(self.address)
882 }
883}
884
885impl L7ListenerHandler for HttpsListener {
886 fn get_sticky_name(&self) -> &str {
887 &self.config.sticky_name
888 }
889
890 fn get_sozu_id_header(&self) -> &str {
891 self.config
892 .sozu_id_header
893 .as_deref()
894 .filter(|s| !s.is_empty())
895 .unwrap_or("Sozu-Id")
896 }
897
898 fn get_connect_timeout(&self) -> u32 {
899 self.config.connect_timeout
900 }
901
902 fn frontend_from_request(
903 &self,
904 host: &str,
905 uri: &str,
906 method: &Method,
907 ) -> Result<RouteResult, FrontendFromRequestError> {
908 let start = Instant::now();
909 let (remaining_input, (hostname, _)) = match hostname_and_port(host.as_bytes()) {
910 Ok(tuple) => tuple,
911 Err(parse_error) => {
912 return Err(FrontendFromRequestError::HostParse {
914 host: host.to_owned(),
915 error: parse_error.to_string(),
916 });
917 }
918 };
919
920 if remaining_input != &b""[..] {
921 return Err(FrontendFromRequestError::InvalidCharsAfterHost(
922 host.to_owned(),
923 ));
924 }
925
926 let host = unsafe { from_utf8_unchecked(hostname) };
935
936 let route = self.fronts.lookup(host, uri, method).map_err(|e| {
937 incr!(names::http::FAILED_BACKEND_MATCHING);
938 FrontendFromRequestError::NoClusterFound(e)
939 })?;
940
941 let now = Instant::now();
942
943 if let Some(cluster) = route.cluster_id.as_deref() {
944 time!(
945 names::event_loop::FRONTEND_MATCHING_TIME,
946 cluster,
947 (now - start).as_millis()
948 );
949 }
950
951 Ok(route)
952 }
953
954 fn get_answers(&self) -> &Rc<RefCell<HttpAnswers>> {
955 &self.answers
956 }
957
958 fn get_h2_flood_config(&self) -> crate::protocol::mux::H2FloodConfig {
959 let defaults = crate::protocol::mux::H2FloodConfig::default();
960 crate::protocol::mux::H2FloodConfig {
961 max_rst_stream_per_window: self
962 .config
963 .h2_max_rst_stream_per_window
964 .unwrap_or(defaults.max_rst_stream_per_window),
965 max_ping_per_window: self
966 .config
967 .h2_max_ping_per_window
968 .unwrap_or(defaults.max_ping_per_window),
969 max_settings_per_window: self
970 .config
971 .h2_max_settings_per_window
972 .unwrap_or(defaults.max_settings_per_window),
973 max_empty_data_per_window: self
974 .config
975 .h2_max_empty_data_per_window
976 .unwrap_or(defaults.max_empty_data_per_window),
977 max_window_update_stream0_per_window: self
978 .config
979 .h2_max_window_update_stream0_per_window
980 .unwrap_or(defaults.max_window_update_stream0_per_window),
981 max_continuation_frames: self
982 .config
983 .h2_max_continuation_frames
984 .unwrap_or(defaults.max_continuation_frames),
985 max_glitch_count: self
986 .config
987 .h2_max_glitch_count
988 .unwrap_or(defaults.max_glitch_count),
989 max_rst_stream_lifetime: self
990 .config
991 .h2_max_rst_stream_lifetime
992 .unwrap_or(defaults.max_rst_stream_lifetime),
993 max_rst_stream_abusive_lifetime: self
994 .config
995 .h2_max_rst_stream_abusive_lifetime
996 .unwrap_or(defaults.max_rst_stream_abusive_lifetime),
997 max_rst_stream_emitted_lifetime: self
998 .config
999 .h2_max_rst_stream_emitted_lifetime
1000 .unwrap_or(defaults.max_rst_stream_emitted_lifetime),
1001 max_header_list_size: self
1002 .config
1003 .h2_max_header_list_size
1004 .unwrap_or(defaults.max_header_list_size),
1005 max_header_table_size: self
1006 .config
1007 .h2_max_header_table_size
1008 .unwrap_or(defaults.max_header_table_size),
1009 }
1010 }
1011
1012 fn get_h2_connection_config(&self) -> crate::protocol::mux::H2ConnectionConfig {
1013 crate::protocol::mux::H2ConnectionConfig::from_optional(
1014 self.config.h2_initial_connection_window,
1015 self.config.h2_max_concurrent_streams,
1016 self.config.h2_stream_shrink_ratio,
1017 )
1018 }
1019
1020 fn get_strict_sni_binding(&self) -> bool {
1021 self.config.strict_sni_binding.unwrap_or(true)
1036 }
1037
1038 fn get_elide_x_real_ip(&self) -> bool {
1039 self.config.elide_x_real_ip.unwrap_or(false)
1040 }
1041
1042 fn get_send_x_real_ip(&self) -> bool {
1043 self.config.send_x_real_ip.unwrap_or(false)
1044 }
1045
1046 fn get_h2_stream_idle_timeout(&self) -> std::time::Duration {
1047 let seconds = self
1054 .config
1055 .h2_stream_idle_timeout_seconds
1056 .map(|s| u64::from(s.max(1)))
1057 .unwrap_or_else(|| u64::from(self.config.back_timeout).max(30));
1058 std::time::Duration::from_secs(seconds)
1059 }
1060
1061 fn get_h2_graceful_shutdown_deadline(&self) -> Option<std::time::Duration> {
1062 match self.config.h2_graceful_shutdown_deadline_seconds {
1063 None => Some(std::time::Duration::from_secs(5)),
1064 Some(0) => None,
1065 Some(s) => Some(std::time::Duration::from_secs(u64::from(s))),
1066 }
1067 }
1068}
1069
1070impl HttpsListener {
1071 pub fn is_http11_disabled(&self) -> bool {
1077 self.config.disable_http11.unwrap_or(false)
1078 }
1079
1080 pub fn resolver(&self) -> &Arc<MutexCertificateResolver> {
1086 &self.resolver
1087 }
1088
1089 pub fn try_new(
1090 config: HttpsListenerConfig,
1091 token: Token,
1092 ) -> Result<HttpsListener, ListenerError> {
1093 let resolver = Arc::new(MutexCertificateResolver::default());
1094
1095 let server_config = Arc::new(Self::create_rustls_context(&config, resolver.to_owned())?);
1096
1097 let answers = {
1098 let mut answers_map = config.answers.clone();
1103 if let Some(ref legacy) = config.http_answers {
1104 crate::protocol::http::answers::merge_legacy_into_map(&mut answers_map, legacy);
1105 }
1106 HttpAnswers::new(&answers_map)
1107 .map_err(|(name, error)| ListenerError::TemplateParse(name, error))?
1108 };
1109
1110 Ok(HttpsListener {
1111 listener: None,
1112 address: config.address.into(),
1113 resolver,
1114 rustls_details: server_config,
1115 active: false,
1116 fronts: Router::new(),
1117 answers: Rc::new(RefCell::new(answers)),
1118 config,
1119 token,
1120 tags: BTreeMap::new(),
1121 })
1122 }
1123
1124 pub fn activate(
1125 &mut self,
1126 registry: &Registry,
1127 tcp_listener: Option<MioTcpListener>,
1128 ) -> Result<Token, ListenerError> {
1129 if self.active {
1130 return Ok(self.token);
1131 }
1132 let address: StdSocketAddr = self.config.address.into();
1133
1134 let mut listener = match tcp_listener {
1135 Some(tcp_listener) => tcp_listener,
1136 None => {
1137 server_bind(address).map_err(|server_bind_error| ListenerError::Activation {
1138 address,
1139 error: server_bind_error.to_string(),
1140 })?
1141 }
1142 };
1143
1144 registry
1145 .register(&mut listener, self.token, Interest::READABLE)
1146 .map_err(ListenerError::SocketRegistration)?;
1147
1148 self.listener = Some(listener);
1149 self.active = true;
1150 Ok(self.token)
1151 }
1152
1153 pub fn create_rustls_context(
1154 config: &HttpsListenerConfig,
1155 resolver: Arc<MutexCertificateResolver>,
1156 ) -> Result<RustlsServerConfig, ListenerError> {
1157 let cipher_names = if config.cipher_list.is_empty() {
1158 DEFAULT_CIPHER_LIST.to_vec()
1159 } else {
1160 config
1161 .cipher_list
1162 .iter()
1163 .map(|s| s.as_str())
1164 .collect::<Vec<_>>()
1165 };
1166
1167 let ciphers = cipher_names
1168 .into_iter()
1169 .filter_map(|cipher| {
1170 cipher_suite_by_name(cipher).or_else(|| {
1171 error!(
1172 "{} unknown or unsupported cipher: {:?}",
1173 log_module_context!(),
1174 cipher
1175 );
1176 None
1177 })
1178 })
1179 .collect::<Vec<_>>();
1180
1181 let versions = config
1182 .versions
1183 .iter()
1184 .filter_map(|version| match TlsVersion::try_from(*version) {
1185 Ok(TlsVersion::TlsV12) => Some(&rustls::version::TLS12),
1186 Ok(TlsVersion::TlsV13) => Some(&rustls::version::TLS13),
1187 Ok(other_version) => {
1188 error!(
1189 "{} unsupported TLS version {:?}",
1190 log_module_context!(),
1191 other_version
1192 );
1193 None
1194 }
1195 Err(_) => {
1196 error!("{} unsupported TLS version", log_module_context!());
1197 None
1198 }
1199 })
1200 .collect::<Vec<_>>();
1201
1202 let kx_groups = if config.groups_list.is_empty() {
1203 default_provider().kx_groups
1204 } else {
1205 config
1206 .groups_list
1207 .iter()
1208 .filter_map(|group| match kx_group_by_name(group) {
1209 Some(kx) => Some(kx),
1210 None => {
1211 debug!("key exchange group {:?} not supported by the compiled crypto provider, skipping", group);
1212 None
1213 }
1214 })
1215 .collect::<Vec<_>>()
1216 };
1217
1218 let provider = CryptoProvider {
1219 cipher_suites: ciphers,
1220 kx_groups,
1221 ..default_provider()
1222 };
1223
1224 let mut server_config = RustlsServerConfig::builder_with_provider(provider.into())
1225 .with_protocol_versions(&versions[..])
1226 .map_err(|err| ListenerError::BuildRustls(err.to_string()))?
1227 .with_no_client_auth()
1228 .with_cert_resolver(resolver);
1229 server_config.send_tls13_tickets = config.send_tls13_tickets as usize;
1230
1231 server_config.alpn_protocols = if config.alpn_protocols.is_empty() {
1232 DEFAULT_ALPN_PROTOCOLS
1233 .iter()
1234 .map(|p| p.as_bytes().to_vec())
1235 .collect()
1236 } else {
1237 config
1238 .alpn_protocols
1239 .iter()
1240 .map(|p| p.as_bytes().to_vec())
1241 .collect()
1242 };
1243
1244 Ok(server_config)
1245 }
1246
1247 pub fn update_config(
1255 &mut self,
1256 patch: &UpdateHttpsListenerConfig,
1257 ) -> Result<(), ListenerError> {
1258 validate_h2_flood_knobs_https(patch)?;
1263 if let Some(ref alpn) = patch.alpn_protocols {
1264 validate_alpn_protocols(&alpn.values)?;
1265 }
1266 if let Some(ref hdr) = patch.sozu_id_header {
1267 validate_sozu_id_header(hdr)?;
1268 }
1269
1270 if let Some(v) = patch.public_address {
1272 self.config.public_address = Some(v);
1273 }
1274 if let Some(v) = patch.expect_proxy {
1275 self.config.expect_proxy = v;
1276 }
1277 if let Some(ref v) = patch.sticky_name {
1278 self.config.sticky_name = v.to_owned();
1279 }
1280 if let Some(v) = patch.front_timeout {
1281 self.config.front_timeout = v;
1282 }
1283 if let Some(v) = patch.back_timeout {
1284 self.config.back_timeout = v;
1285 }
1286 if let Some(v) = patch.connect_timeout {
1287 self.config.connect_timeout = v;
1288 }
1289 if let Some(v) = patch.request_timeout {
1290 self.config.request_timeout = v;
1291 }
1292 if let Some(v) = patch.strict_sni_binding {
1293 self.config.strict_sni_binding = Some(v);
1294 }
1295 if let Some(v) = patch.disable_http11 {
1296 self.config.disable_http11 = Some(v);
1297 }
1298 if let Some(ref v) = patch.sozu_id_header {
1299 self.config.sozu_id_header = Some(v.to_owned());
1300 }
1301 if let Some(v) = patch.elide_x_real_ip {
1302 self.config.elide_x_real_ip = Some(v);
1303 }
1304 if let Some(v) = patch.send_x_real_ip {
1305 self.config.send_x_real_ip = Some(v);
1306 }
1307
1308 if let Some(v) = patch.h2_max_rst_stream_per_window {
1310 self.config.h2_max_rst_stream_per_window = Some(v);
1311 }
1312 if let Some(v) = patch.h2_max_ping_per_window {
1313 self.config.h2_max_ping_per_window = Some(v);
1314 }
1315 if let Some(v) = patch.h2_max_settings_per_window {
1316 self.config.h2_max_settings_per_window = Some(v);
1317 }
1318 if let Some(v) = patch.h2_max_empty_data_per_window {
1319 self.config.h2_max_empty_data_per_window = Some(v);
1320 }
1321 if let Some(v) = patch.h2_max_continuation_frames {
1322 self.config.h2_max_continuation_frames = Some(v);
1323 }
1324 if let Some(v) = patch.h2_max_glitch_count {
1325 self.config.h2_max_glitch_count = Some(v);
1326 }
1327 if let Some(v) = patch.h2_initial_connection_window {
1328 self.config.h2_initial_connection_window = Some(v);
1329 }
1330 if let Some(v) = patch.h2_max_concurrent_streams {
1331 self.config.h2_max_concurrent_streams = Some(v);
1332 }
1333 if let Some(v) = patch.h2_stream_shrink_ratio {
1334 self.config.h2_stream_shrink_ratio = Some(v);
1335 }
1336 if let Some(v) = patch.h2_max_rst_stream_lifetime {
1337 self.config.h2_max_rst_stream_lifetime = Some(v);
1338 }
1339 if let Some(v) = patch.h2_max_rst_stream_abusive_lifetime {
1340 self.config.h2_max_rst_stream_abusive_lifetime = Some(v);
1341 }
1342 if let Some(v) = patch.h2_max_rst_stream_emitted_lifetime {
1343 self.config.h2_max_rst_stream_emitted_lifetime = Some(v);
1344 }
1345 if let Some(v) = patch.h2_max_header_list_size {
1346 self.config.h2_max_header_list_size = Some(v);
1347 }
1348 if let Some(v) = patch.h2_max_header_table_size {
1349 self.config.h2_max_header_table_size = Some(v);
1350 }
1351 if let Some(v) = patch.h2_stream_idle_timeout_seconds {
1352 self.config.h2_stream_idle_timeout_seconds = Some(v);
1353 }
1354 if let Some(v) = patch.h2_graceful_shutdown_deadline_seconds {
1355 self.config.h2_graceful_shutdown_deadline_seconds = Some(v);
1356 }
1357 if let Some(v) = patch.h2_max_window_update_stream0_per_window {
1358 self.config.h2_max_window_update_stream0_per_window = Some(v);
1359 }
1360
1361 if let Some(ref alpn_wrapper) = patch.alpn_protocols {
1371 let mut candidate = self.config.clone();
1372 candidate.alpn_protocols = alpn_wrapper.values.clone();
1373 let new_rustls = Arc::new(Self::create_rustls_context(
1374 &candidate,
1375 self.resolver.clone(),
1376 )?);
1377 self.config.alpn_protocols = alpn_wrapper.values.clone();
1379 self.rustls_details = new_rustls;
1380 }
1381
1382 let answers_changed = patch.http_answers.is_some() || !patch.answers.is_empty();
1387 if answers_changed {
1388 if let Some(ref new_answers) = patch.http_answers {
1389 crate::sozu_command::state::merge_custom_http_answers(
1390 &mut self.config.http_answers,
1391 new_answers,
1392 );
1393 }
1394 for (code, body) in &patch.answers {
1395 if !body.is_empty() {
1396 self.config.answers.insert(code.clone(), body.clone());
1397 }
1398 }
1399
1400 let mut answers_map = self.config.answers.clone();
1401 if let Some(ref legacy) = self.config.http_answers {
1402 crate::protocol::http::answers::merge_legacy_into_map(&mut answers_map, legacy);
1403 }
1404 let mut rebuilt = HttpAnswers::new(&answers_map)
1405 .map_err(|(name, error)| ListenerError::TemplateParse(name, error))?;
1406 let preserved = std::mem::take(&mut self.answers.borrow_mut().cluster_answers);
1407 rebuilt.cluster_answers = preserved;
1408 *self.answers.borrow_mut() = rebuilt;
1409 }
1410
1411 if let Some(new_hsts) = patch.hsts {
1430 if new_hsts.enabled.is_none() {
1431 return Err(ListenerError::HstsEnabledRequired);
1432 }
1433 self.config.hsts = Some(new_hsts);
1434 let refreshed = self
1435 .fronts
1436 .refresh_inheriting_hsts(self.config.hsts.as_ref());
1437 for _ in 0..refreshed {
1438 crate::incr!(names::http::HSTS_FRONTEND_REFRESHED);
1439 }
1440 info!(
1441 "{} HTTPS listener {:?} HSTS default patched; refreshed {} inheriting \
1442 frontend(s). Explicit per-frontend overrides untouched.",
1443 log_module_context!(),
1444 self.config.address,
1445 refreshed,
1446 );
1447 crate::incr!(names::http::HSTS_LISTENER_DEFAULT_PATCHED);
1448 }
1449
1450 Ok(())
1451 }
1452
1453 pub fn add_https_front(&mut self, tls_front: HttpFrontend) -> Result<(), ListenerError> {
1454 self.add_https_front_with_hsts_origin(tls_front, crate::router::HstsOrigin::Explicit)
1455 }
1456
1457 pub fn add_https_front_with_hsts_origin(
1464 &mut self,
1465 tls_front: HttpFrontend,
1466 hsts_origin: crate::router::HstsOrigin,
1467 ) -> Result<(), ListenerError> {
1468 self.fronts
1469 .add_http_front_with_hsts_origin(&tls_front, hsts_origin)
1470 .map_err(ListenerError::AddFrontend)
1471 }
1472
1473 pub fn remove_https_front(&mut self, tls_front: HttpFrontend) -> Result<(), ListenerError> {
1474 debug!(
1475 "{} removing tls_front {:?}",
1476 log_module_context!(),
1477 tls_front
1478 );
1479 self.fronts
1480 .remove_http_front(&tls_front)
1481 .map_err(ListenerError::RemoveFrontend)
1482 }
1483
1484 fn accept(&mut self) -> Result<MioTcpStream, AcceptError> {
1485 if let Some(ref sock) = self.listener {
1486 sock.accept()
1487 .map_err(|e| match e.kind() {
1488 ErrorKind::WouldBlock => AcceptError::WouldBlock,
1489 _ => {
1490 error!("{} accept() IO error: {:?}", log_module_context!(), e);
1491 AcceptError::IoError
1492 }
1493 })
1494 .map(|(sock, _)| sock)
1495 } else {
1496 error!(
1497 "{} cannot accept connections, no listening socket available",
1498 log_module_context!()
1499 );
1500 Err(AcceptError::IoError)
1501 }
1502 }
1503}
1504
1505pub struct HttpsProxy {
1506 listeners: HashMap<Token, Rc<RefCell<HttpsListener>>>,
1507 clusters: HashMap<ClusterId, Cluster>,
1508 backends: Rc<RefCell<BackendMap>>,
1509 pool: Rc<RefCell<Pool>>,
1510 registry: Registry,
1511 sessions: Rc<RefCell<SessionManager>>,
1512}
1513
1514impl HttpsProxy {
1515 pub fn new(
1516 registry: Registry,
1517 sessions: Rc<RefCell<SessionManager>>,
1518 pool: Rc<RefCell<Pool>>,
1519 backends: Rc<RefCell<BackendMap>>,
1520 ) -> HttpsProxy {
1521 HttpsProxy {
1522 listeners: HashMap::new(),
1523 clusters: HashMap::new(),
1524 backends,
1525 pool,
1526 registry,
1527 sessions,
1528 }
1529 }
1530
1531 pub fn add_listener(
1532 &mut self,
1533 config: HttpsListenerConfig,
1534 token: Token,
1535 ) -> Result<Token, ProxyError> {
1536 match self.listeners.entry(token) {
1537 Entry::Vacant(entry) => {
1538 let https_listener =
1539 HttpsListener::try_new(config, token).map_err(ProxyError::AddListener)?;
1540 entry.insert(Rc::new(RefCell::new(https_listener)));
1541 Ok(token)
1542 }
1543 _ => Err(ProxyError::ListenerAlreadyPresent),
1544 }
1545 }
1546
1547 pub fn remove_listener(
1548 &mut self,
1549 remove: RemoveListener,
1550 ) -> Result<Option<ResponseContent>, ProxyError> {
1551 let len = self.listeners.len();
1552
1553 let remove_address = remove.address.into();
1554 self.listeners
1555 .retain(|_, listener| listener.borrow().address != remove_address);
1556
1557 if !self.listeners.len() < len {
1558 info!(
1559 "{} no HTTPS listener to remove at address {}",
1560 log_module_context!(),
1561 remove_address
1562 )
1563 }
1564 Ok(None)
1565 }
1566
1567 pub fn soft_stop(&mut self) -> Result<(), ProxyError> {
1568 let listeners: HashMap<_, _> = self.listeners.drain().collect();
1569 let mut socket_errors = vec![];
1570 for (_, l) in listeners.iter() {
1571 if let Some(mut sock) = l.borrow_mut().listener.take() {
1572 debug!("{} deregistering socket {:?}", log_module_context!(), sock);
1573 if let Err(e) = self.registry.deregister(&mut sock) {
1574 let error = format!("socket {sock:?}: {e:?}");
1575 socket_errors.push(error);
1576 }
1577 }
1578 }
1579
1580 if !socket_errors.is_empty() {
1581 return Err(ProxyError::SoftStop {
1582 proxy_protocol: "HTTPS".to_string(),
1583 error: format!("Error deregistering listen sockets: {socket_errors:?}"),
1584 });
1585 }
1586
1587 Ok(())
1588 }
1589
1590 pub fn hard_stop(&mut self) -> Result<(), ProxyError> {
1591 let mut listeners: HashMap<_, _> = self.listeners.drain().collect();
1592 let mut socket_errors = vec![];
1593 for (_, l) in listeners.drain() {
1594 if let Some(mut sock) = l.borrow_mut().listener.take() {
1595 debug!("{} deregistering socket {:?}", log_module_context!(), sock);
1596 if let Err(e) = self.registry.deregister(&mut sock) {
1597 let error = format!("socket {sock:?}: {e:?}");
1598 socket_errors.push(error);
1599 }
1600 }
1601 }
1602
1603 if !socket_errors.is_empty() {
1604 return Err(ProxyError::HardStop {
1605 proxy_protocol: "HTTPS".to_string(),
1606 error: format!("Error deregistering listen sockets: {socket_errors:?}"),
1607 });
1608 }
1609
1610 Ok(())
1611 }
1612
1613 pub fn query_all_certificates(&mut self) -> Result<Option<ResponseContent>, ProxyError> {
1614 let certificates = self
1615 .listeners
1616 .values()
1617 .map(|listener| {
1618 let owned = listener.borrow();
1619 let resolver = unwrap_msg!(owned.resolver.0.lock());
1620 let certificate_summaries = resolver
1621 .domains
1622 .to_hashmap()
1623 .drain()
1624 .map(|(k, fingerprint)| CertificateSummary {
1625 domain: String::from_utf8(k).unwrap(),
1626 fingerprint: fingerprint.to_string(),
1627 })
1628 .collect();
1629
1630 CertificatesByAddress {
1631 address: owned.address.into(),
1632 certificate_summaries,
1633 }
1634 })
1635 .collect();
1636
1637 info!(
1638 "{} got Certificates::All query, answering with {:?}",
1639 log_module_context!(),
1640 certificates
1641 );
1642
1643 Ok(Some(
1644 ContentType::CertificatesByAddress(ListOfCertificatesByAddress { certificates }).into(),
1645 ))
1646 }
1647
1648 pub fn query_certificate_for_domain(
1649 &mut self,
1650 domain: String,
1651 ) -> Result<Option<ResponseContent>, ProxyError> {
1652 let certificates = self
1653 .listeners
1654 .values()
1655 .map(|listener| {
1656 let owned = listener.borrow();
1657 let resolver = unwrap_msg!(owned.resolver.0.lock());
1658 let mut certificate_summaries = vec![];
1659
1660 if let Some((k, fingerprint)) = resolver.domain_lookup(domain.as_bytes(), true) {
1661 certificate_summaries.push(CertificateSummary {
1662 domain: String::from_utf8(k.to_vec()).unwrap(),
1663 fingerprint: fingerprint.to_string(),
1664 });
1665 }
1666 CertificatesByAddress {
1667 address: owned.address.into(),
1668 certificate_summaries,
1669 }
1670 })
1671 .collect();
1672
1673 info!(
1674 "{} got Certificates::Domain({}) query, answering with {:?}",
1675 log_module_context!(),
1676 domain,
1677 certificates
1678 );
1679
1680 Ok(Some(
1681 ContentType::CertificatesByAddress(ListOfCertificatesByAddress { certificates }).into(),
1682 ))
1683 }
1684
1685 pub fn activate_listener(
1686 &mut self,
1687 addr: &StdSocketAddr,
1688 tcp_listener: Option<MioTcpListener>,
1689 ) -> Result<Token, ProxyError> {
1690 let listener = self
1691 .listeners
1692 .values()
1693 .find(|listener| listener.borrow().address == *addr)
1694 .ok_or(ProxyError::NoListenerFound(addr.to_owned()))?;
1695
1696 listener
1697 .borrow_mut()
1698 .activate(&self.registry, tcp_listener)
1699 .map_err(|listener_error| ProxyError::ListenerActivation {
1700 address: *addr,
1701 listener_error,
1702 })
1703 }
1704
1705 pub fn give_back_listeners(&mut self) -> Vec<(StdSocketAddr, MioTcpListener)> {
1706 self.listeners
1707 .values()
1708 .filter_map(|listener| {
1709 let mut owned = listener.borrow_mut();
1710 if let Some(listener) = owned.listener.take() {
1711 owned.active = false;
1714 return Some((owned.address, listener));
1715 }
1716
1717 None
1718 })
1719 .collect()
1720 }
1721
1722 pub fn give_back_listener(
1723 &mut self,
1724 address: StdSocketAddr,
1725 ) -> Result<(Token, MioTcpListener), ProxyError> {
1726 let listener = self
1727 .listeners
1728 .values()
1729 .find(|listener| listener.borrow().address == address)
1730 .ok_or(ProxyError::NoListenerFound(address))?;
1731
1732 let mut owned = listener.borrow_mut();
1733
1734 let taken_listener = owned
1735 .listener
1736 .take()
1737 .ok_or(ProxyError::UnactivatedListener)?;
1738
1739 owned.active = false;
1742
1743 Ok((owned.token, taken_listener))
1744 }
1745
1746 pub fn update_listener(&mut self, patch: UpdateHttpsListenerConfig) -> Result<(), ProxyError> {
1748 let address: std::net::SocketAddr = patch.address.into();
1749 let listener = self
1750 .listeners
1751 .values()
1752 .find(|l| l.borrow().address == address)
1753 .ok_or(ProxyError::NoListenerFound(address))?;
1754 listener
1755 .borrow_mut()
1756 .update_config(&patch)
1757 .map_err(|listener_error| ProxyError::ListenerActivation {
1758 address,
1759 listener_error,
1760 })
1761 }
1762
1763 pub fn add_cluster(
1764 &mut self,
1765 mut cluster: Cluster,
1766 ) -> Result<Option<ResponseContent>, ProxyError> {
1767 let mut cluster_overrides = cluster.answers.clone();
1768 if let Some(answer_503) = cluster.answer_503.take() {
1769 cluster_overrides
1770 .entry("503".to_owned())
1771 .or_insert(answer_503);
1772 }
1773 if !cluster_overrides.is_empty() {
1774 for listener in self.listeners.values() {
1775 listener
1776 .borrow()
1777 .answers
1778 .borrow_mut()
1779 .add_cluster_answers(&cluster.cluster_id, &cluster_overrides)
1780 .map_err(|(status, error)| {
1781 ProxyError::AddCluster(ListenerError::TemplateParse(status, error))
1782 })?;
1783 }
1784 }
1785 self.clusters.insert(cluster.cluster_id.clone(), cluster);
1786 Ok(None)
1787 }
1788
1789 pub fn remove_cluster(
1790 &mut self,
1791 cluster_id: &str,
1792 ) -> Result<Option<ResponseContent>, ProxyError> {
1793 self.clusters.remove(cluster_id);
1794 for listener in self.listeners.values() {
1795 listener
1796 .borrow()
1797 .answers
1798 .borrow_mut()
1799 .remove_cluster_answers(cluster_id);
1800 }
1801
1802 Ok(None)
1803 }
1804
1805 pub fn add_https_frontend(
1806 &mut self,
1807 front: RequestHttpFrontend,
1808 ) -> Result<Option<ResponseContent>, ProxyError> {
1809 let mut front = front.clone().to_frontend().map_err(|request_error| {
1810 ProxyError::WrongInputFrontend {
1811 front: Box::new(front),
1812 error: request_error.to_string(),
1813 }
1814 })?;
1815
1816 let mut listener = self
1817 .listeners
1818 .values()
1819 .find(|l| l.borrow().address == front.address)
1820 .ok_or(ProxyError::NoListenerFound(front.address))?
1821 .borrow_mut();
1822
1823 let hsts_origin = if front.hsts.is_none() && listener.config.hsts.is_some() {
1836 front.hsts = listener.config.hsts;
1837 crate::router::HstsOrigin::InheritedFromListenerDefault
1838 } else {
1839 crate::router::HstsOrigin::Explicit
1840 };
1841
1842 listener.set_tags(front.hostname.to_owned(), front.tags.to_owned());
1843 listener
1844 .add_https_front_with_hsts_origin(front, hsts_origin)
1845 .map_err(ProxyError::AddFrontend)?;
1846 Ok(None)
1847 }
1848
1849 pub fn remove_https_frontend(
1850 &mut self,
1851 front: RequestHttpFrontend,
1852 ) -> Result<Option<ResponseContent>, ProxyError> {
1853 let front = front.clone().to_frontend().map_err(|request_error| {
1854 ProxyError::WrongInputFrontend {
1855 front: Box::new(front),
1856 error: request_error.to_string(),
1857 }
1858 })?;
1859
1860 let mut listener = self
1861 .listeners
1862 .values()
1863 .find(|l| l.borrow().address == front.address)
1864 .ok_or(ProxyError::NoListenerFound(front.address))?
1865 .borrow_mut();
1866
1867 let hostname = front.hostname.to_owned();
1868
1869 listener
1870 .remove_https_front(front)
1871 .map_err(ProxyError::RemoveFrontend)?;
1872
1873 if !listener.fronts.has_hostname(&hostname) {
1874 listener.set_tags(hostname, None);
1875 }
1876 Ok(None)
1877 }
1878
1879 pub fn add_certificate(
1880 &mut self,
1881 add_certificate: AddCertificate,
1882 ) -> Result<Option<ResponseContent>, ProxyError> {
1883 let address = add_certificate.address.into();
1884
1885 let listener = self
1886 .listeners
1887 .values()
1888 .find(|l| l.borrow().address == address)
1889 .ok_or(ProxyError::NoListenerFound(address))?
1890 .borrow_mut();
1891
1892 let mut resolver = listener
1893 .resolver
1894 .0
1895 .lock()
1896 .map_err(|e| ProxyError::Lock(e.to_string()))?;
1897
1898 resolver
1899 .add_certificate(&add_certificate)
1900 .map_err(ProxyError::AddCertificate)?;
1901
1902 Ok(None)
1903 }
1904
1905 pub fn remove_certificate(
1907 &mut self,
1908 remove_certificate: RemoveCertificate,
1909 ) -> Result<Option<ResponseContent>, ProxyError> {
1910 let address = remove_certificate.address.into();
1911
1912 let fingerprint = Fingerprint(
1913 hex::decode(&remove_certificate.fingerprint)
1914 .map_err(ProxyError::WrongCertificateFingerprint)?,
1915 );
1916
1917 let listener = self
1918 .listeners
1919 .values()
1920 .find(|l| l.borrow().address == address)
1921 .ok_or(ProxyError::NoListenerFound(address))?
1922 .borrow_mut();
1923
1924 let mut resolver = listener
1925 .resolver
1926 .0
1927 .lock()
1928 .map_err(|e| ProxyError::Lock(e.to_string()))?;
1929
1930 resolver
1931 .remove_certificate(&fingerprint)
1932 .map_err(ProxyError::RemoveCertificate)?;
1933
1934 Ok(None)
1935 }
1936
1937 pub fn replace_certificate(
1939 &mut self,
1940 replace_certificate: ReplaceCertificate,
1941 ) -> Result<Option<ResponseContent>, ProxyError> {
1942 let address = replace_certificate.address.into();
1943
1944 let listener = self
1945 .listeners
1946 .values()
1947 .find(|l| l.borrow().address == address)
1948 .ok_or(ProxyError::NoListenerFound(address))?
1949 .borrow_mut();
1950
1951 let mut resolver = listener
1952 .resolver
1953 .0
1954 .lock()
1955 .map_err(|e| ProxyError::Lock(e.to_string()))?;
1956
1957 resolver
1958 .replace_certificate(&replace_certificate)
1959 .map_err(ProxyError::ReplaceCertificate)?;
1960
1961 Ok(None)
1962 }
1963}
1964
1965impl ProxyConfiguration for HttpsProxy {
1966 fn accept(&mut self, token: ListenToken) -> Result<MioTcpStream, AcceptError> {
1967 match self.listeners.get(&Token(token.0)) {
1968 Some(listener) => listener.borrow_mut().accept(),
1969 None => Err(AcceptError::IoError),
1970 }
1971 }
1972
1973 fn create_session(
1974 &mut self,
1975 mut frontend_sock: MioTcpStream,
1976 token: ListenToken,
1977 wait_time: Duration,
1978 proxy: Rc<RefCell<Self>>,
1979 ) -> Result<(), AcceptError> {
1980 let listener = self
1981 .listeners
1982 .get(&Token(token.0))
1983 .ok_or(AcceptError::IoError)?;
1984 if let Err(e) = frontend_sock.set_nodelay(true) {
1985 error!(
1986 "{} error setting nodelay on front socket({:?}): {:?}",
1987 log_module_context!(),
1988 frontend_sock,
1989 e
1990 );
1991 }
1992
1993 let owned = listener.borrow();
1994 let rustls_details = ServerConnection::new(owned.rustls_details.clone()).map_err(|e| {
1995 error!(
1996 "{} failed to create server session: {:?}",
1997 log_module_context!(),
1998 e
1999 );
2000 AcceptError::IoError
2001 })?;
2002
2003 let mut session_manager = self.sessions.borrow_mut();
2004 let entry = session_manager.slab.vacant_entry();
2005 let session_token = Token(entry.key());
2006
2007 self.registry
2008 .register(
2009 &mut frontend_sock,
2010 session_token,
2011 Interest::READABLE | Interest::WRITABLE,
2012 )
2013 .map_err(|register_error| {
2014 error!(
2015 "{} error registering front socket({:?}): {:?}",
2016 log_module_context!(),
2017 frontend_sock,
2018 register_error
2019 );
2020 AcceptError::RegisterError
2021 })?;
2022
2023 let public_address: StdSocketAddr = match owned.config.public_address {
2024 Some(pub_addr) => pub_addr.into(),
2025 None => owned.config.address.into(),
2026 };
2027
2028 let session = Rc::new(RefCell::new(HttpsSession::new(
2029 Duration::from_secs(owned.config.back_timeout as u64),
2030 Duration::from_secs(owned.config.connect_timeout as u64),
2031 Duration::from_secs(owned.config.front_timeout as u64),
2032 Duration::from_secs(owned.config.request_timeout as u64),
2033 owned.config.expect_proxy,
2034 listener.clone(),
2035 Rc::downgrade(&self.pool),
2036 proxy,
2037 public_address,
2038 rustls_details,
2039 frontend_sock,
2040 session_token,
2041 wait_time,
2042 )));
2043 entry.insert(session);
2044
2045 Ok(())
2046 }
2047
2048 fn notify(&mut self, request: WorkerRequest) -> WorkerResponse {
2049 let request_id = request.id.clone();
2050
2051 let request_type = match request.content.request_type {
2052 Some(t) => t,
2053 None => return WorkerResponse::error(request_id, "Empty request"),
2054 };
2055
2056 let content_result = match request_type {
2057 RequestType::AddCluster(cluster) => {
2058 debug!(
2059 "{} {} add cluster {:?}",
2060 log_module_context!(),
2061 request_id,
2062 cluster
2063 );
2064 self.add_cluster(cluster)
2065 }
2066 RequestType::RemoveCluster(cluster_id) => {
2067 debug!(
2068 "{} {} remove cluster {:?}",
2069 log_module_context!(),
2070 request_id,
2071 cluster_id
2072 );
2073 self.remove_cluster(&cluster_id)
2074 }
2075 RequestType::AddHttpsFrontend(front) => {
2076 debug!(
2077 "{} {} add https front {:?}",
2078 log_module_context!(),
2079 request_id,
2080 front
2081 );
2082 self.add_https_frontend(front)
2083 }
2084 RequestType::RemoveHttpsFrontend(front) => {
2085 debug!(
2086 "{} {} remove https front {:?}",
2087 log_module_context!(),
2088 request_id,
2089 front
2090 );
2091 self.remove_https_frontend(front)
2092 }
2093 RequestType::AddCertificate(add_certificate) => {
2094 debug!(
2095 "{} {} add certificate: {:?}",
2096 log_module_context!(),
2097 request_id,
2098 add_certificate
2099 );
2100 self.add_certificate(add_certificate)
2101 }
2102 RequestType::RemoveCertificate(remove_certificate) => {
2103 debug!(
2104 "{} {} remove certificate: {:?}",
2105 log_module_context!(),
2106 request_id,
2107 remove_certificate
2108 );
2109 self.remove_certificate(remove_certificate)
2110 }
2111 RequestType::ReplaceCertificate(replace_certificate) => {
2112 debug!(
2113 "{} {} replace certificate: {:?}",
2114 log_module_context!(),
2115 request_id,
2116 replace_certificate
2117 );
2118 self.replace_certificate(replace_certificate)
2119 }
2120 RequestType::RemoveListener(remove) => {
2121 debug!(
2122 "{} removing HTTPS listener at address {:?}",
2123 log_module_context!(),
2124 remove.address
2125 );
2126 self.remove_listener(remove)
2127 }
2128 RequestType::SoftStop(_) => {
2129 debug!(
2130 "{} {} processing soft shutdown",
2131 log_module_context!(),
2132 request_id
2133 );
2134 match self.soft_stop() {
2135 Ok(_) => {
2136 info!(
2137 "{} {} soft stop successful",
2138 log_module_context!(),
2139 request_id
2140 );
2141 return WorkerResponse::processing(request.id);
2142 }
2143 Err(e) => Err(e),
2144 }
2145 }
2146 RequestType::HardStop(_) => {
2147 debug!(
2148 "{} {} processing hard shutdown",
2149 log_module_context!(),
2150 request_id
2151 );
2152 match self.hard_stop() {
2153 Ok(_) => {
2154 debug!(
2155 "{} {} hard stop successful",
2156 log_module_context!(),
2157 request_id
2158 );
2159 return WorkerResponse::processing(request.id);
2160 }
2161 Err(e) => Err(e),
2162 }
2163 }
2164 RequestType::Status(_) => {
2165 debug!("{} {} status", log_module_context!(), request_id);
2166 Ok(None)
2167 }
2168 RequestType::QueryCertificatesFromWorkers(filters) => {
2169 if let Some(domain) = filters.domain {
2170 debug!(
2171 "{} {} query certificate for domain {}",
2172 log_module_context!(),
2173 request_id,
2174 domain
2175 );
2176 self.query_certificate_for_domain(domain)
2177 } else {
2178 debug!(
2179 "{} {} query all certificates",
2180 log_module_context!(),
2181 request_id
2182 );
2183 self.query_all_certificates()
2184 }
2185 }
2186 other_request => {
2187 debug!(
2188 "{} {} unsupported message for HTTPS proxy, ignoring {:?}",
2189 log_module_context!(),
2190 request.id,
2191 other_request
2192 );
2193 Err(ProxyError::UnsupportedMessage)
2194 }
2195 };
2196
2197 match content_result {
2198 Ok(content) => {
2199 debug!("{} {} successful", log_module_context!(), request_id);
2200 match content {
2201 Some(content) => WorkerResponse::ok_with_content(request_id, content),
2202 None => WorkerResponse::ok(request_id),
2203 }
2204 }
2205 Err(proxy_error) => {
2206 debug!(
2207 "{} {} unsuccessful: {}",
2208 log_module_context!(),
2209 request_id,
2210 proxy_error
2211 );
2212 WorkerResponse::error(request_id, proxy_error)
2213 }
2214 }
2215 }
2216}
2217impl L7Proxy for HttpsProxy {
2218 fn kind(&self) -> ListenerType {
2219 ListenerType::Https
2220 }
2221
2222 fn register_socket(
2223 &self,
2224 socket: &mut MioTcpStream,
2225 token: Token,
2226 interest: Interest,
2227 ) -> Result<(), std::io::Error> {
2228 self.registry.register(socket, token, interest)
2229 }
2230
2231 fn deregister_socket(&self, tcp_stream: &mut MioTcpStream) -> Result<(), std::io::Error> {
2232 self.registry.deregister(tcp_stream)
2233 }
2234
2235 fn add_session(&self, session: Rc<RefCell<dyn ProxySession>>) -> Token {
2236 let mut session_manager = self.sessions.borrow_mut();
2237 let entry = session_manager.slab.vacant_entry();
2238 let token = Token(entry.key());
2239 let _entry = entry.insert(session);
2240 token
2241 }
2242
2243 fn remove_session(&self, token: Token) -> bool {
2244 let mut sessions = self.sessions.borrow_mut();
2245 sessions.untrack_all_cluster_ip(token);
2248 sessions.slab.try_remove(token.0).is_some()
2249 }
2250
2251 fn backends(&self) -> Rc<RefCell<BackendMap>> {
2252 self.backends.clone()
2253 }
2254
2255 fn clusters(&self) -> &HashMap<ClusterId, Cluster> {
2256 &self.clusters
2257 }
2258
2259 fn sessions(&self) -> Rc<RefCell<SessionManager>> {
2260 self.sessions.clone()
2261 }
2262}
2263
2264fn rustls_version_str(version: ProtocolVersion) -> &'static str {
2266 match version {
2267 ProtocolVersion::SSLv2 => "tls.version.SSLv2",
2268 ProtocolVersion::SSLv3 => "tls.version.SSLv3",
2269 ProtocolVersion::TLSv1_0 => "tls.version.TLSv1_0",
2270 ProtocolVersion::TLSv1_1 => "tls.version.TLSv1_1",
2271 ProtocolVersion::TLSv1_2 => "tls.version.TLSv1_2",
2272 ProtocolVersion::TLSv1_3 => "tls.version.TLSv1_3",
2273 ProtocolVersion::DTLSv1_0 => "tls.version.DTLSv1_0",
2274 ProtocolVersion::DTLSv1_2 => "tls.version.DTLSv1_2",
2275 ProtocolVersion::DTLSv1_3 => "tls.version.DTLSv1_3",
2276 ProtocolVersion::Unknown(_) => "tls.version.Unknown",
2277 _ => "tls.version.unimplemented",
2278 }
2279}
2280
2281pub(crate) fn rustls_version_label(version: ProtocolVersion) -> Option<&'static str> {
2288 match version {
2289 ProtocolVersion::SSLv2 => Some("SSLv2"),
2290 ProtocolVersion::SSLv3 => Some("SSLv3"),
2291 ProtocolVersion::TLSv1_0 => Some("TLSv1.0"),
2292 ProtocolVersion::TLSv1_1 => Some("TLSv1.1"),
2293 ProtocolVersion::TLSv1_2 => Some("TLSv1.2"),
2294 ProtocolVersion::TLSv1_3 => Some("TLSv1.3"),
2295 ProtocolVersion::DTLSv1_0 => Some("DTLSv1.0"),
2296 ProtocolVersion::DTLSv1_2 => Some("DTLSv1.2"),
2297 ProtocolVersion::DTLSv1_3 => Some("DTLSv1.3"),
2298 _ => None,
2299 }
2300}
2301
2302fn rustls_ciphersuite_str(cipher: SupportedCipherSuite) -> &'static str {
2304 match cipher.suite() {
2305 CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 => {
2306 "tls.cipher.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
2307 }
2308 CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => {
2309 "tls.cipher.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
2310 }
2311 CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 => {
2312 "tls.cipher.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
2313 }
2314 CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 => {
2315 "tls.cipher.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
2316 }
2317 CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 => {
2318 "tls.cipher.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
2319 }
2320 CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 => {
2321 "tls.cipher.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
2322 }
2323 CipherSuite::TLS13_CHACHA20_POLY1305_SHA256 => "tls.cipher.TLS13_CHACHA20_POLY1305_SHA256",
2324 CipherSuite::TLS13_AES_256_GCM_SHA384 => "tls.cipher.TLS13_AES_256_GCM_SHA384",
2325 CipherSuite::TLS13_AES_128_GCM_SHA256 => "tls.cipher.TLS13_AES_128_GCM_SHA256",
2326 _ => "tls.cipher.Unsupported",
2327 }
2328}
2329
2330pub(crate) fn rustls_ciphersuite_label(cipher: SupportedCipherSuite) -> Option<&'static str> {
2337 match cipher.suite() {
2338 CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 => {
2339 Some("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
2340 }
2341 CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => {
2342 Some("TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
2343 }
2344 CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 => {
2345 Some("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
2346 }
2347 CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 => {
2348 Some("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384")
2349 }
2350 CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 => {
2351 Some("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
2352 }
2353 CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 => {
2354 Some("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384")
2355 }
2356 CipherSuite::TLS13_CHACHA20_POLY1305_SHA256 => Some("TLS13_CHACHA20_POLY1305_SHA256"),
2357 CipherSuite::TLS13_AES_256_GCM_SHA384 => Some("TLS13_AES_256_GCM_SHA384"),
2358 CipherSuite::TLS13_AES_128_GCM_SHA256 => Some("TLS13_AES_128_GCM_SHA256"),
2359 _ => None,
2360 }
2361}
2362
2363pub mod testing {
2364 use crate::testing::*;
2365
2366 pub fn start_https_worker(
2368 config: HttpsListenerConfig,
2369 channel: ProxyChannel,
2370 max_buffers: usize,
2371 buffer_size: usize,
2372 ) -> anyhow::Result<()> {
2373 let address = config.address.into();
2374
2375 let ServerParts {
2376 event_loop,
2377 registry,
2378 sessions,
2379 pool,
2380 backends,
2381 client_scm_socket: _,
2382 server_scm_socket,
2383 server_config,
2384 } = prebuild_server(max_buffers, buffer_size, true)?;
2385
2386 let token = {
2387 let mut sessions = sessions.borrow_mut();
2388 let entry = sessions.slab.vacant_entry();
2389 let key = entry.key();
2390 let _ = entry.insert(Rc::new(RefCell::new(ListenSession {
2391 protocol: Protocol::HTTPSListen,
2392 })));
2393 Token(key)
2394 };
2395
2396 let mut proxy = HttpsProxy::new(registry, sessions.clone(), pool.clone(), backends.clone());
2397 proxy
2398 .add_listener(config, token)
2399 .with_context(|| "Failed at creating adding the listener")?;
2400 proxy
2401 .activate_listener(&address, None)
2402 .with_context(|| "Failed at creating activating the listener")?;
2403
2404 let mut server = Server::new(
2405 event_loop,
2406 channel,
2407 server_scm_socket,
2408 sessions,
2409 pool,
2410 backends,
2411 None,
2412 Some(proxy),
2413 None,
2414 server_config,
2415 None,
2416 false,
2417 )
2418 .with_context(|| "Failed at creating server")?;
2419
2420 debug!("{} starting event loop", log_module_context!());
2421 server.run();
2422 debug!("{} ending event loop", log_module_context!());
2423 Ok(())
2424 }
2425}
2426
2427#[cfg(test)]
2428mod tests {
2429 use std::sync::Arc;
2430
2431 use sozu_command::{config::ListenerBuilder, proto::command::SocketAddress};
2432
2433 use super::*;
2434 use crate::router::{MethodRule, PathRule, Route, Router, pattern_trie::TrieNode};
2435
2436 #[test]
2454 fn frontend_from_request_test() {
2455 let cluster_id1 = "cluster_1".to_owned();
2456 let cluster_id2 = "cluster_2".to_owned();
2457 let cluster_id3 = "cluster_3".to_owned();
2458 let uri1 = "/".to_owned();
2459 let uri2 = "/yolo".to_owned();
2460 let uri3 = "/yolo/swag".to_owned();
2461
2462 let mut fronts = Router::new();
2463 assert!(fronts.add_tree_rule(
2464 "lolcatho.st".as_bytes(),
2465 &PathRule::Prefix(uri1),
2466 &MethodRule::new(None),
2467 &Route::ClusterId(cluster_id1.clone())
2468 ));
2469 assert!(fronts.add_tree_rule(
2470 "lolcatho.st".as_bytes(),
2471 &PathRule::Prefix(uri2),
2472 &MethodRule::new(None),
2473 &Route::ClusterId(cluster_id2)
2474 ));
2475 assert!(fronts.add_tree_rule(
2476 "lolcatho.st".as_bytes(),
2477 &PathRule::Prefix(uri3),
2478 &MethodRule::new(None),
2479 &Route::ClusterId(cluster_id3)
2480 ));
2481 assert!(fronts.add_tree_rule(
2482 "other.domain".as_bytes(),
2483 &PathRule::Prefix("test".to_string()),
2484 &MethodRule::new(None),
2485 &Route::ClusterId(cluster_id1)
2486 ));
2487
2488 let address = SocketAddress::new_v4(127, 0, 0, 1, 1032);
2489 let resolver = Arc::new(MutexCertificateResolver::default());
2490
2491 let crypto_provider = Arc::new(default_provider());
2492
2493 let server_config = RustlsServerConfig::builder_with_provider(crypto_provider)
2494 .with_protocol_versions(&[&rustls::version::TLS12, &rustls::version::TLS13])
2495 .expect("could not create rustls config server")
2496 .with_no_client_auth()
2497 .with_cert_resolver(resolver.clone());
2498
2499 let rustls_details = Arc::new(server_config);
2500
2501 let default_config = ListenerBuilder::new_https(address)
2502 .to_tls(None)
2503 .expect("Could not create default HTTPS listener config");
2504
2505 println!("it doesn't even matter");
2506
2507 let listener = HttpsListener {
2508 listener: None,
2509 address: address.into(),
2510 fronts,
2511 rustls_details,
2512 resolver,
2513 answers: Rc::new(RefCell::new(
2514 HttpAnswers::new(&std::collections::BTreeMap::new()).unwrap(),
2515 )),
2516 config: default_config,
2517 token: Token(0),
2518 active: true,
2519 tags: BTreeMap::new(),
2520 };
2521
2522 println!("TEST {}", line!());
2523 let frontend1 = listener.frontend_from_request("lolcatho.st", "/", &Method::Get);
2524 assert_eq!(
2525 frontend1
2526 .expect("should find a frontend")
2527 .cluster_id
2528 .as_deref(),
2529 Some("cluster_1")
2530 );
2531 println!("TEST {}", line!());
2532 let frontend2 = listener.frontend_from_request("lolcatho.st", "/test", &Method::Get);
2533 assert_eq!(
2534 frontend2
2535 .expect("should find a frontend")
2536 .cluster_id
2537 .as_deref(),
2538 Some("cluster_1")
2539 );
2540 println!("TEST {}", line!());
2541 let frontend3 = listener.frontend_from_request("lolcatho.st", "/yolo/test", &Method::Get);
2542 assert_eq!(
2543 frontend3
2544 .expect("should find a frontend")
2545 .cluster_id
2546 .as_deref(),
2547 Some("cluster_2")
2548 );
2549 println!("TEST {}", line!());
2550 let frontend4 = listener.frontend_from_request("lolcatho.st", "/yolo/swag", &Method::Get);
2551 assert_eq!(
2552 frontend4
2553 .expect("should find a frontend")
2554 .cluster_id
2555 .as_deref(),
2556 Some("cluster_3")
2557 );
2558 println!("TEST {}", line!());
2559 let frontend5 = listener.frontend_from_request("domain", "/", &Method::Get);
2560 assert!(frontend5.is_err());
2561 }
2563
2564 #[test]
2565 fn wildcard_certificate_names() {
2566 let mut trie = TrieNode::root();
2567
2568 trie.domain_insert("*.services.clever-cloud.com".as_bytes().to_vec(), 1u8);
2569 trie.domain_insert("*.clever-cloud.com".as_bytes().to_vec(), 2u8);
2570 trie.domain_insert("services.clever-cloud.com".as_bytes().to_vec(), 0u8);
2571 trie.domain_insert(
2572 "abprefix.services.clever-cloud.com".as_bytes().to_vec(),
2573 3u8,
2574 );
2575 trie.domain_insert(
2576 "cdprefix.services.clever-cloud.com".as_bytes().to_vec(),
2577 4u8,
2578 );
2579
2580 let res = trie.domain_lookup(b"test.services.clever-cloud.com", true);
2581 println!("query result: {res:?}");
2582
2583 assert_eq!(
2584 trie.domain_lookup(b"pgstudio.services.clever-cloud.com", true),
2585 Some(&("*.services.clever-cloud.com".as_bytes().to_vec(), 1u8))
2586 );
2587 assert_eq!(
2588 trie.domain_lookup(b"test-prefix.services.clever-cloud.com", true),
2589 Some(&("*.services.clever-cloud.com".as_bytes().to_vec(), 1u8))
2590 );
2591 }
2592
2593 #[test]
2594 fn wildcard_with_subdomains() {
2595 let mut trie = TrieNode::root();
2596
2597 trie.domain_insert("*.test.example.com".as_bytes().to_vec(), 1u8);
2598 trie.domain_insert("hello.sub.test.example.com".as_bytes().to_vec(), 2u8);
2599
2600 let res = trie.domain_lookup(b"sub.test.example.com", true);
2601 println!("query result: {res:?}");
2602
2603 assert_eq!(
2604 trie.domain_lookup(b"sub.test.example.com", true),
2605 Some(&("*.test.example.com".as_bytes().to_vec(), 1u8))
2606 );
2607 assert_eq!(
2608 trie.domain_lookup(b"hello.sub.test.example.com", true),
2609 Some(&("hello.sub.test.example.com".as_bytes().to_vec(), 2u8))
2610 );
2611
2612 let mut trie = TrieNode::root();
2614
2615 trie.domain_insert("hello.sub.test.example.com".as_bytes().to_vec(), 2u8);
2616 trie.domain_insert("*.test.example.com".as_bytes().to_vec(), 1u8);
2617
2618 let res = trie.domain_lookup(b"sub.test.example.com", true);
2619 println!("query result: {res:?}");
2620
2621 assert_eq!(
2622 trie.domain_lookup(b"sub.test.example.com", true),
2623 Some(&("*.test.example.com".as_bytes().to_vec(), 1u8))
2624 );
2625 assert_eq!(
2626 trie.domain_lookup(b"hello.sub.test.example.com", true),
2627 Some(&("hello.sub.test.example.com".as_bytes().to_vec(), 2u8))
2628 );
2629 }
2630
2631 #[test]
2632 fn h2_stream_idle_timeout_inherits_back_timeout() {
2633 use std::time::Duration;
2634
2635 let address = SocketAddress::new_v4(127, 0, 0, 1, 1041);
2636 let build = |back_timeout: u32, explicit: Option<u32>| -> HttpsListener {
2637 let mut cfg = ListenerBuilder::new_https(address)
2638 .to_tls(None)
2639 .expect("default HTTPS listener config");
2640 cfg.back_timeout = back_timeout;
2641 cfg.h2_stream_idle_timeout_seconds = explicit;
2642 HttpsListener::try_new(cfg, Token(0)).expect("build listener")
2643 };
2644
2645 assert_eq!(
2647 build(180, None).get_h2_stream_idle_timeout(),
2648 Duration::from_secs(180)
2649 );
2650
2651 assert_eq!(
2653 build(5, None).get_h2_stream_idle_timeout(),
2654 Duration::from_secs(30)
2655 );
2656
2657 assert_eq!(
2659 build(180, Some(10)).get_h2_stream_idle_timeout(),
2660 Duration::from_secs(10)
2661 );
2662 assert_eq!(
2663 build(5, Some(600)).get_h2_stream_idle_timeout(),
2664 Duration::from_secs(600)
2665 );
2666
2667 assert_eq!(
2669 build(180, Some(0)).get_h2_stream_idle_timeout(),
2670 Duration::from_secs(1)
2671 );
2672 }
2673}