@@ -256,6 +256,10 @@ struct FormState {
256256 /// drop the user's setting. Not currently exposed as a UI control;
257257 /// users edit `block_quic` directly in `config.json` (Issue #213).
258258 block_quic : bool ,
259+ /// Round-tripped from config.json and exposed beside QUIC blocking.
260+ /// Default true to push WebRTC apps toward TCP TURN instead of slow
261+ /// UDP ICE retries.
262+ block_stun : bool ,
259263 /// Round-tripped from config.json. Not exposed as a UI control —
260264 /// users edit `disable_padding` directly when needed (Issue #391).
261265 /// Default false (padding active).
@@ -387,6 +391,7 @@ fn load_form() -> (FormState, Option<String>) {
387391 youtube_via_relay : c. youtube_via_relay ,
388392 passthrough_hosts : c. passthrough_hosts . clone ( ) ,
389393 block_quic : c. block_quic ,
394+ block_stun : c. block_stun ,
390395 disable_padding : c. disable_padding ,
391396 force_http1 : c. force_http1 ,
392397 tunnel_doh : c. tunnel_doh ,
@@ -426,6 +431,7 @@ fn load_form() -> (FormState, Option<String>) {
426431 youtube_via_relay : false ,
427432 passthrough_hosts : Vec :: new ( ) ,
428433 block_quic : true ,
434+ block_stun : true ,
429435 disable_padding : false ,
430436 force_http1 : false ,
431437 tunnel_doh : true ,
@@ -587,6 +593,7 @@ impl FormState {
587593 // control yet). Round-trip through the file so save
588594 // doesn't drop a user-set true.
589595 block_quic : self . block_quic ,
596+ block_stun : self . block_stun ,
590597 // Issue #391: disable_padding is config-only for now.
591598 // Round-trip preserves the user's choice.
592599 disable_padding : self . disable_padding ,
@@ -688,6 +695,9 @@ struct ConfigWire<'a> {
688695 /// emit only when the user has explicitly disabled the block.
689696 #[ serde( skip_serializing_if = "is_true" ) ]
690697 block_doh : bool ,
698+ /// Default true. Emit only when the user disables STUN/TURN blocking.
699+ #[ serde( skip_serializing_if = "is_true" ) ]
700+ block_stun : bool ,
691701 #[ serde( skip_serializing_if = "Vec::is_empty" ) ]
692702 fronting_groups : & ' a Vec < FrontingGroup > ,
693703 /// Auto-blacklist tuning + batch timeout (#391, #444, #430). Skip
@@ -781,6 +791,7 @@ impl<'a> From<&'a Config> for ConfigWire<'a> {
781791 tunnel_doh : c. tunnel_doh ,
782792 bypass_doh_hosts : & c. bypass_doh_hosts ,
783793 block_doh : c. block_doh ,
794+ block_stun : c. block_stun ,
784795 fronting_groups : & c. fronting_groups ,
785796 auto_blacklist_strikes : c. auto_blacklist_strikes ,
786797 auto_blacklist_window_secs : c. auto_blacklist_window_secs ,
@@ -1274,6 +1285,15 @@ impl eframe::App for App {
12741285 Issue #213, #793.",
12751286 ) ;
12761287 } ) ;
1288+ ui. horizontal ( |ui| {
1289+ ui. add_space ( 120.0 + 8.0 ) ;
1290+ ui. checkbox ( & mut self . form . block_stun , "Block STUN/TURN UDP" )
1291+ . on_hover_text (
1292+ "Drop WebRTC STUN/TURN UDP ports 3478, 5349, and 19302 so apps \
1293+ such as Meet, Discord, and WhatsApp move to TCP TURN instead of \
1294+ waiting on UDP ICE retries.",
1295+ ) ;
1296+ } ) ;
12771297 } ) ;
12781298 } ) ;
12791299
0 commit comments