1- // start-tor.cs - builds to start-tor.exe (compile with build-start-tor.ps1)
1+ // start-tor.cs - builds to start-tor.exe (compile with build-start-tor.ps1)
22// Portable Tor launcher for Iran. Expected layout next to this exe:
33// start-tor.exe
44// data\
77// bridges\ <- obfs4_tested.txt, webtunnel_tested.txt, vanilla_tested.txt
88// data\ <- runtime state (tor.log, cached-*, keys)
99// The user picks a connection mode (direct / webtunnel / obfs4 / vanilla); the
10- // program writes data\torrc and starts tor, then enables the Windows system
11- // proxy (HTTP 127.0.0.1:8118). Press Enter to stop and restore the proxy.
12- // Subcommands: --newcircuit, --stop, --bootstrap-only [mode].
10+ // program writes data\torrc and starts tor. Tor is NOT set as the system proxy
11+ // automatically: press Ctrl+P (Ctrl+ح on a Persian keyboard) to toggle the
12+ // Windows system proxy (HTTP 127.0.0.1:8118) on/off. Ctrl+C stops tor.
13+ // Subcommands: --newcircuit, --stop, --update-bridges, --bootstrap-only [mode].
1314using System ;
1415using System . Collections . Generic ;
1516using System . Diagnostics ;
1617using System . IO ;
18+ using System . Net ;
1719using System . Net . Sockets ;
1820using System . Reflection ;
1921using System . Runtime . InteropServices ;
@@ -44,6 +46,9 @@ internal static class Program
4446
4547 private static readonly string [ ] ModeNames = { "direct" , "webtunnel" , "obfs4" , "vanilla" } ;
4648 private static readonly string [ ] BridgeFiles = { "" , "webtunnel_tested.txt" , "obfs4_tested.txt" , "vanilla_tested.txt" } ;
49+ private static readonly string [ ] AllBridgeFiles = { "obfs4_tested.txt" , "webtunnel_tested.txt" , "vanilla_tested.txt" } ;
50+ private const string BridgesBaseUrl =
51+ "https://raw.githubusercontent.com/Delta-Kronecker/Tor-Bridges-Collector/refs/heads/main/bridge" ;
4752
4853 private static Process torProc ;
4954 private static bool cleaned ;
@@ -221,6 +226,74 @@ private static bool WriteTorrc(int mode)
221226 return true ;
222227 }
223228
229+ private static int CountBridgeLines ( string path )
230+ {
231+ int n = 0 ;
232+ foreach ( string line in File . ReadAllLines ( path ) )
233+ {
234+ string t = line . Trim ( ) ;
235+ if ( t . Length == 0 || t . StartsWith ( "#" ) ) continue ;
236+ if ( t . Contains ( "2001:db8" ) ) continue ;
237+ n ++ ;
238+ }
239+ return n ;
240+ }
241+
242+ private static int UpdateBridges ( )
243+ {
244+ try
245+ {
246+ ServicePointManager . SecurityProtocol = SecurityProtocolType . Tls12 ;
247+ }
248+ catch { }
249+
250+ Directory . CreateDirectory ( BridgesDir ) ;
251+ Console . WriteLine ( "Updating bridge files from " + BridgesBaseUrl ) ;
252+ Console . WriteLine ( " -> " + BridgesDir ) ;
253+ Console . WriteLine ( ) ;
254+
255+ int ok = 0 ;
256+ foreach ( string f in AllBridgeFiles )
257+ {
258+ string dest = Path . Combine ( BridgesDir , f ) ;
259+ string tmp = dest + ".tmp" ;
260+ string url = BridgesBaseUrl + "/" + f ;
261+ try
262+ {
263+ using ( WebClient wc = new WebClient ( ) )
264+ {
265+ wc . Headers [ HttpRequestHeader . UserAgent ] = "start-tor-updater/1.0" ;
266+ wc . DownloadFile ( url , tmp ) ;
267+ }
268+ int n = CountBridgeLines ( tmp ) ;
269+ if ( n == 0 )
270+ {
271+ Console . WriteLine ( "[!] " + f + ": downloaded file has no usable bridges - keeping old." ) ;
272+ try { File . Delete ( tmp ) ; } catch { }
273+ continue ;
274+ }
275+ File . Copy ( tmp , dest , true ) ;
276+ try { File . Delete ( tmp ) ; } catch { }
277+ Console . WriteLine ( "[i] " + f + ": " + n + " bridges - updated." ) ;
278+ ok ++ ;
279+ }
280+ catch ( Exception ex )
281+ {
282+ Console . WriteLine ( "[x] " + f + ": " + ex . Message ) ;
283+ }
284+ }
285+
286+ Console . WriteLine ( ) ;
287+ if ( ok == AllBridgeFiles . Length )
288+ {
289+ Console . WriteLine ( "All bridge files are up to date." ) ;
290+ return 0 ;
291+ }
292+ Console . WriteLine ( "Updated " + ok + " of " + AllBridgeFiles . Length +
293+ " bridge files (restart tor to use the new bridges)." ) ;
294+ return ok > 0 ? 0 : 1 ;
295+ }
296+
224297 private static int StopTor ( )
225298 {
226299 Process p = FindTor ( ) ;
@@ -252,6 +325,11 @@ private static int Main(string[] args)
252325 {
253326 return StopTor ( ) ;
254327 }
328+ if ( args . Length > 0 &&
329+ ( args [ 0 ] == "--update-bridges" || args [ 0 ] == "--update" || args [ 0 ] == "-u" ) )
330+ {
331+ return UpdateBridges ( ) ;
332+ }
255333
256334 int mode = - 1 ;
257335 bool bootstrapOnly = false ;
@@ -368,6 +446,7 @@ private static int Main(string[] args)
368446
369447 Console . WriteLine ( ) ;
370448 Console . WriteLine ( "Bootstrapped 100% - Tor is UP." ) ;
449+ Console . WriteLine ( ) ;
371450
372451 if ( bootstrapOnly )
373452 {
@@ -376,14 +455,40 @@ private static int Main(string[] args)
376455 return 0 ;
377456 }
378457
379- SetSystemProxy ( true ) ;
380- Console . WriteLine ( "System proxy set to 127.0.0.1:8118" ) ;
381- Console . WriteLine ( " SOCKS5 127.0.0.1:9050" ) ;
382- Console . WriteLine ( " HTTP 127.0.0.1:8118" ) ;
383- Console . WriteLine ( " DNS 127.0.0.1:53530" ) ;
458+ bool proxyOn = false ;
459+ Console . WriteLine ( " Ctrl+P (Ctrl+ح) toggle the Windows system proxy on/off" ) ;
460+ Console . WriteLine ( " Ctrl+C stop Tor and exit" ) ;
461+ Console . WriteLine ( " Proxy OFF" ) ;
384462 Console . WriteLine ( ) ;
385- Console . WriteLine ( "Press Enter to stop Tor and restore the system proxy..." ) ;
386- try { Console . ReadLine ( ) ; } catch { }
463+ while ( true )
464+ {
465+ bool alive = true ;
466+ if ( torProc != null )
467+ {
468+ try { torProc . Refresh ( ) ; alive = ! torProc . HasExited ; }
469+ catch { alive = false ; }
470+ }
471+ if ( ! alive )
472+ {
473+ Console . WriteLine ( "[x] tor exited with code " + ( torProc != null ? torProc . ExitCode : - 1 ) + "." ) ;
474+ break ;
475+ }
476+ try
477+ {
478+ if ( Console . KeyAvailable )
479+ {
480+ ConsoleKeyInfo ki = Console . ReadKey ( true ) ;
481+ if ( ( ki . Modifiers & ConsoleModifiers . Control ) != 0 && ki . Key == ConsoleKey . P )
482+ {
483+ proxyOn = ! proxyOn ;
484+ SetSystemProxy ( proxyOn ) ;
485+ Console . WriteLine ( " [i] System proxy " + ( proxyOn ? "ON (127.0.0.1:8118)" : "OFF" ) ) ;
486+ }
487+ }
488+ }
489+ catch { }
490+ Thread . Sleep ( 150 ) ;
491+ }
387492
388493 Cleanup ( ) ;
389494 Console . WriteLine ( "Tor stopped; system proxy restored." ) ;
0 commit comments