@@ -13,7 +13,7 @@ use mhrv_rs::cert_installer::{install_ca, reconcile_sudo_environment, remove_ca}
1313use mhrv_rs:: config:: { Config , FrontingGroup , ScriptId } ;
1414use mhrv_rs:: data_dir;
1515use mhrv_rs:: domain_fronter:: { DomainFronter , DEFAULT_GOOGLE_SNI_POOL } ;
16- use mhrv_rs:: lan_utils:: { detect_lan_ip , is_share_on_lan} ;
16+ use mhrv_rs:: lan_utils:: is_share_on_lan;
1717use mhrv_rs:: mitm:: { MitmCertManager , CA_CERT_FILE } ;
1818use mhrv_rs:: proxy_server:: ProxyServer ;
1919use mhrv_rs:: { scan_ips, scan_sni, test_cmd} ;
@@ -919,98 +919,60 @@ impl eframe::App for App {
919919 . labelled_by ( label_id) ;
920920 } ) ;
921921
922- // Network sharing: phones, tablets, other laptops on the
923- // same Wi-Fi can use this proxy when the bind address is
924- // 0.0.0.0 instead of 127.0.0.1. We expose this as a
925- // single-checkbox UI rather than the raw `listen_host`
926- // text field — typing `0.0.0.0` from memory is enough of
927- // a friction point that almost no one does it. Power
928- // users with a custom bind IP (specific NIC) can still
929- // edit `listen_host` directly in `config.toml`; we
930- // detect that case and show a "Custom bind" badge so
931- // the checkbox doesn't silently overwrite their setting
932- // on the next Save.
922+ // Network sharing is disabled until inbound proxy auth
923+ // exists. The config validator rejects non-loopback binds;
924+ // keep the form aligned so Save never writes a value that
925+ // the next startup will fail closed.
933926 //
934927 // Snapshot the relevant flags before entering form_row's
935- // closure — we need to mutate `self.form.listen_host`
936- // inside the closure when the checkbox toggles, so we
937- // can't hold a borrow on it through the closure.
928+ // closure — we may reset `self.form.listen_host` inside
929+ // the closure, so avoid holding a borrow through it.
938930 let listen_host_snapshot = self . form . listen_host . trim ( ) . to_string ( ) ;
939- let listen_port_snapshot = self . form . listen_port . trim ( ) . to_string ( ) ;
940- let socks5_port_snapshot = self . form . socks5_port . trim ( ) . to_string ( ) ;
941931 let was_share_on_lan = is_share_on_lan ( & listen_host_snapshot) ;
942932 let lower_snapshot = listen_host_snapshot. to_ascii_lowercase ( ) ;
943933 let is_custom_bind = !listen_host_snapshot. is_empty ( )
944934 && !was_share_on_lan
945935 && lower_snapshot != "127.0.0.1"
946936 && lower_snapshot != "localhost" ;
947- let mut new_listen_host: Option < String > = None ;
948937 form_row ( ui, "Network" , Some (
949- "By default the proxy is reachable only from this computer. \
950- Turn this on to let phones, tablets, and other laptops on the \
951- same Wi-Fi (or a hotspot you're sharing) use it too. The \
952- other devices then point their HTTP / SOCKS5 proxy at the \
953- LAN IP shown below. Make sure your firewall lets in the proxy \
954- port — macOS pops up a Firewall prompt the first time."
938+ "The proxy is reachable only from this computer. Non-loopback \
939+ binds are rejected until HTTP/SOCKS inbound authentication is \
940+ implemented, which prevents accidental open-proxy exposure on \
941+ shared Wi-Fi or hotspots."
955942 ) , |ui, _label_id| {
956- if is_custom_bind {
957- // The user manually wrote a specific bind IP —
958- // don't let the checkbox stomp on it. Show what
959- // they have and tell them to edit config.toml
960- // if they want to change it.
943+ if was_share_on_lan || is_custom_bind {
961944 ui. vertical ( |ui| {
962945 ui. label ( egui:: RichText :: new ( format ! (
963- "Custom bind: {}" ,
946+ "Unsafe bind configured : {}" ,
964947 listen_host_snapshot
965- ) ) . color ( egui:: Color32 :: from_rgb ( 220 , 180 , 100 ) ) ) ;
966- ui. small ( "Edit `listen_host` in config.toml to change." ) ;
948+ ) ) . color ( ERR_RED ) ) ;
949+ ui. small (
950+ "Current builds reject non-loopback binds. Set \
951+ listen_host to 127.0.0.1 in config.toml."
952+ ) ;
953+ if ui. small_button ( "Reset to loopback" ) . clicked ( ) {
954+ self . form . listen_host = "127.0.0.1" . to_string ( ) ;
955+ }
967956 } ) ;
968957 } else {
969- let mut share = was_share_on_lan;
970- if ui. checkbox ( & mut share, "Share with other devices on my Wi-Fi / network" ) . changed ( ) {
971- new_listen_host = Some ( if share {
972- "0.0.0.0" . to_string ( )
973- } else {
974- "127.0.0.1" . to_string ( )
975- } ) ;
976- }
977- if share {
978- // detect_lan_ip() opens a UDP socket and
979- // asks the kernel which interface a packet
980- // to a public IP would use. Cheap (no
981- // syscall does network I/O) and accurate
982- // (it's the same selection any outbound
983- // connection would make).
984- match detect_lan_ip ( ) {
985- Some ( ip) => {
986- let port = if listen_port_snapshot. is_empty ( ) {
987- "8085"
988- } else {
989- listen_port_snapshot. as_str ( )
990- } ;
991- let socks_port = if socks5_port_snapshot. is_empty ( ) {
992- "8086"
993- } else {
994- socks5_port_snapshot. as_str ( )
995- } ;
996- ui. small ( egui:: RichText :: new ( format ! (
997- "Other devices: HTTP {}:{} · SOCKS5 {}:{}" ,
998- ip, port, ip, socks_port,
999- ) ) . color ( egui:: Color32 :: from_rgb ( 120 , 200 , 140 ) ) ) ;
1000- }
1001- None => {
1002- ui. small ( egui:: RichText :: new (
1003- "Couldn't detect your LAN IP. Find it in System Settings \
1004- → Network → Wi-Fi → Details (macOS) or `ipconfig` (Windows)."
1005- ) . color ( egui:: Color32 :: from_rgb ( 220 , 180 , 100 ) ) ) ;
1006- }
1007- }
1008- }
958+ self . form . listen_host = "127.0.0.1" . to_string ( ) ;
959+ let mut share = false ;
960+ ui. add_enabled (
961+ false ,
962+ egui:: Checkbox :: new (
963+ & mut share,
964+ "Share with other devices on my Wi-Fi / network" ,
965+ ) ,
966+ )
967+ . on_disabled_hover_text (
968+ "LAN sharing will return after inbound proxy authentication is available." ,
969+ ) ;
970+ ui. small (
971+ egui:: RichText :: new ( "Loopback only: HTTP/SOCKS accept local connections." )
972+ . color ( egui:: Color32 :: from_rgb ( 120 , 200 , 140 ) ) ,
973+ ) ;
1009974 }
1010975 } ) ;
1011- if let Some ( updated) = new_listen_host {
1012- self . form . listen_host = updated;
1013- }
1014976
1015977 ui. horizontal ( |ui| {
1016978 ui. add_sized (
0 commit comments