func exit() { lg.Infoln("alkasir is shutting down") atexitMu.Lock() // this lock should be kept, one shutdown should be enough for everyone. lg.Flush() if err := clientconfig.Write(); err != nil { lg.Errorf("could not save config file: %s", err.Error()) } lg.V(9).Infoln("running atexit funcs") for _, f := range atexitFuncs { funcName := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() lg.V(10).Infoln("Running at exit func", funcName) f() lg.V(10).Infoln("Finished at exit func", funcName) } atexitFuncs = atexitFuncs[:0] lg.V(9).Infoln("atexit funcs done") lg.V(9).Infoln("stopping connectionmanager") service.StopConnectionManager() lg.V(9).Infoln("stopping services") service.StopAll() lg.V(9).Infoln("services stopped") lg.V(9).Infoln("waiting for UI shutdown to finish") uiRunning.Wait() lg.V(9).Infoln("ui shut down") lg.Flush() lg.Infoln("alkasir shutdown complete") lg.Flush() time.Sleep(time.Millisecond * 1) os.Exit(0) }
// Init initializes the server. func Init() error { lg.SetSrcHighlight("alkasir/cmd", "alkasir/pkg") lg.CopyStandardLogTo("INFO") lg.V(1).Info("Log v-level:", lg.Verbosity()) lg.V(1).Info("Active country codes:", shared.CountryCodes) lg.Flush() if *datadirFlag == "" { u, err := user.Current() if err != nil { lg.Fatal(err) } datadir = filepath.Join(u.HomeDir, ".alkasir-central") } else { datadir = *datadirFlag } validCountryCodes = make(map[string]bool, len(shared.CountryCodes)) validCountryCodesMu.Lock() for _, cc := range shared.CountryCodes { validCountryCodes[cc] = true } validCountryCodesMu.Unlock() err := InitDB() if err != nil { lg.Fatalln(err) return err } redisPool = newRedisPool(*redisServer, *redisPassword) internet.SetDataDir(filepath.Join(datadir, "internet")) countryFile := filepath.Join(datadir, "internet", "GeoLite2-Country.mmdb") if _, err := os.Stat(countryFile); os.IsNotExist(err) { // http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz lg.Fatalf("cannot enable IP2CountryCode lookups, %s is missing", countryFile) } else { var err error mmCountryDB, err = maxminddb.Open(countryFile) if err != nil { lg.Fatal(err) } } cityFile := filepath.Join(datadir, "internet", "GeoLite2-City.mmdb") if _, err := os.Stat(cityFile); os.IsNotExist(err) { // http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz lg.Warningf("cannot enable IP2CityGeoNameID lookups, %s is missing", cityFile) } else { mmCityDB, err = maxminddb.Open(cityFile) if err != nil { lg.Fatal(err) } // defer mmCityDB.Close() } return nil }
// Run runs the initialized server. func Run() { var wg sync.WaitGroup // start monitor server go startMonitoring(*monitorBindAddr) // start the getpublic ip updater. go func() { _ = shared.GetPublicIPAddr() }() wg.Add(1) go func() { defer wg.Done() lg.V(2).Infoln("Loading recent sessions from postgres...") recents, err := sqlDB.RecentSuggestionSessions(20000) if err != nil { lg.Fatal(err) } db.SessionTokens.Reset(recents) lg.V(2).Infof("Loaded %d sessions from postgres...", len(recents)) lg.Flush() }() wg.Add(1) go func() { defer wg.Done() conn := redisPool.Get() defer conn.Close() lg.V(2).Infoln("BGPDump refresh started...") n, err := internet.RefreshBGPDump(conn) lg.V(2).Infof("BGPDump refresh ended, %d items added.", n) lg.Flush() if err != nil { if *offline { lg.Infoln("offline", err) } else { lg.Fatal(err) } } }() wg.Add(1) go func() { defer wg.Done() conn := redisPool.Get() defer conn.Close() lg.V(2).Infoln("CIDRReport refresh started...") n, err := internet.RefreshCIDRReport(conn) lg.V(2).Infof("CIDRReport refresh ended, %d items added", n) if err != nil { if *offline { lg.Infoln("offline", err) } else { lg.Fatal(err) } } }() wg.Wait() // start signal handling wg.Add(1) go func() { ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT) lg.Infoln(<-ch) wg.Done() }() internetClient := db.NewInternetClient(redisPool) maxmindClient := db.NewMaxmindClient(mmCountryDB, mmCityDB) clients := db.Clients{ DB: sqlDB, Internet: internetClient, Maxmind: maxmindClient, } // start http json api server go func(addr string, dba db.Clients) { mux, err := apiMux(dba) lg.Info("Starting http server", addr) err = http.ListenAndServe(addr, mux) if err != nil { lg.Fatal(err) } }(*apiBindAddr, clients) // start http export api server go func(addr string, dba db.Clients) { if *exportApiSecretKey == "" { lg.Warningln("exportApiSecretKey flag/env not set, will not start export api server") b := make([]byte, 32) _, err := rand.Read(b) if err != nil { lg.Fatalf("random generator not functioning...") return } suggestedkey := base64.StdEncoding.EncodeToString(b) lg.Infoln("suggested export key:", suggestedkey) return } key, err := base64.StdEncoding.DecodeString(*exportApiSecretKey) if err != nil { lg.Fatalf("could not decode export api secret key: %s", *exportApiSecretKey) } mux, err := apiMuxExport(dba, key) lg.Info("Starting export api server", addr) err = http.ListenAndServe(addr, mux) if err != nil { lg.Fatal(err) } }(*exportApiBindAddr, clients) go analysis.StartAnalysis(clients) startMeasurer(clients) wg.Wait() }
func main() { lg.SetSrcHighlight("alkasir/cmd", "alkasir/pkg") lg.CopyStandardLogTo("INFO") lg.V(1).Info("Log v-level:", lg.Verbosity()) lg.V(1).Info("Active country codes:", shared.CountryCodes) lg.Flush() if obfs4proxy.Check() { monitorBindAddr := flag.String("monitorAddr", "localhost:8037", "port to bind monitor server to") flag.Parse() go startMonitoring(*monitorBindAddr) obfs4proxy.Run(obfs4proxy.Config{ LogLevel: "INFO", EnableLogging: true, UnsafeLogging: false, }) os.Exit(0) } monitorBindAddr := flag.String("monitorAddr", "localhost:8036", "port to bind monitor server to") flag.Parse() go startMonitoring(*monitorBindAddr) // server := ptc.Server{ // Config: ptc.Config{ // StateLocation: ".", // Command: os.Args[0], // }, // ORPort: "127.0.0.1:23450", // Methods: []ptc.SMethod{ptc.SMethod{ // MethodName: "obfs4", // BindAddr: "127.0.0.1:4423", // Args: ptc.Args{ // "node-id": []string{"4d3e4561149907025571827a1277661b5f9fca46"}, // "private-key": []string{"7886017adfd178cd139e91250dddee0b2af8ab6cf93f1fe9a7a469d3a13a3067"}, // "public-key": []string{"4393d7641042620a60881a72ebb47ef8c5a5840acb4f858e5c0026cb2e75fd6f"}, // "drbg-seed": []string{"c23e876ddc408cc392317e017a6796a96161f76d8dd90522"}, // "iat-mode": []string{"0"}, // }, // }, // }, // } configdir := os.Getenv("ALKASIR_TORPT_CONFIGDIR") configfile := filepath.Join(configdir, "alkasir-torpt-server.json") data, err := ioutil.ReadFile(configfile) if err != nil { panic(err) } server := ptc.Server{} err = json.Unmarshal(data, &server) if err != nil { panic(err) } server.Command = os.Args[0] go socks5server(server.ORPort) err = server.Start() if err != nil { panic(err) } var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() err := server.Wait() if err != nil { log.Println(err) } }() wg.Wait() }