示例#1
0
文件: misc.go 项目: thomasf/alkasir
// StopAll stops all services, blocks until everything is shut down.
func StopAll() {
	err := ManagedServices.stopAll()
	if err != nil {
		lg.Error(err)
	}

}
示例#2
0
func (d *DebugResponse) WriteToDisk() error {
	dir := d.filename()
	if err := os.MkdirAll(dir, 0775); err != nil {
		panic(err)
	}

	writeTextFile := func(data []string, basename string) error {
		filename := filepath.Join(dir, basename+".txt")
		f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0665)
		if err != nil {
			return err
		}
		defer f.Close()
		for _, v := range data {
			_, err := f.WriteString(v + "\n")
			if err != nil {
				return err
			}
		}
		return nil
	}

	writeJsonFile := func(data interface{}, basename string) error {
		bytes, err := json.MarshalIndent(&data, "", "  ")
		if err != nil {
			panic(err)
		}
		filename := filepath.Join(dir, basename+".json")
		err = ioutil.WriteFile(filename, bytes, 0665)
		if err != nil {
			return err
		}
		return nil
	}

	failed := false

	for _, v := range []error{
		writeJsonFile(d.Header, "header"),
		writeTextFile(d.Log, "log"),
		writeTextFile(d.Heap, "heap"),
		writeTextFile(d.GoRoutines, "goroutines"),
		writeTextFile(d.Block, "block"),
		writeTextFile(d.ThreadCreate, "threadcreate"),
		writeJsonFile(d.Config, "config"),
	} {
		if v != nil {
			failed = true
			lg.Error(v)
		}
	}

	if failed {
		return fmt.Errorf("errors writing out report %s", dir)
	}
	lg.Infof("wrote report for %s", dir)

	return nil
}
示例#3
0
func startMeasurer(dbclients db.Clients) {

	for n := 0; n < 10; n++ {

		go func() {
			var ps PreparedSample
			err := ps.Update(dbclients)
			if err != nil {
				lg.Error("could not resolve public ip address", err)
			}

			lg.V(5).Infoln("starting measurer")
			for r := range requestMeasurements {
				lg.V(50).Infoln("got measurement", r)
				if ps.lastUpdated.Before(time.Now().Add(-time.Hour * 5)) {
					lg.V(15).Info("updating prepared sample", ps)
					err := ps.Update(dbclients)
					if err != nil {
						lg.Warning(err)
					}

				}
			measurerLoop:
				for _, v := range r.measurers {
					measurement, err := v.Measure()
					if err != nil {
						lg.Errorf("could not measure:%v error:%s", v, err.Error())
						continue measurerLoop
					}
					switch measurement.Type() {
					case sampletypes.DNSQuery, sampletypes.HTTPHeader:

						data, err := measurement.Marshal()
						if err != nil {
							lg.Errorf("could not decode %v error:%s", measurement, err.Error())
							continue measurerLoop
						}
						err = dbclients.DB.InsertSample(db.Sample{
							Host:        measurement.Host(),
							CountryCode: ps.s.CountryCode,
							Token:       r.token,
							ASN:         ps.s.ASN,
							Type:        measurement.Type().String(),
							Origin:      sampleorigins.Central.String(),
							Data:        data,
						})
						if err != nil {
							lg.Errorln(err.Error())
							continue measurerLoop
						}
					default:
						lg.Errorf("could not measure:%v error:%s", v, err.Error())
						continue measurerLoop
					}
				}
			}
		}()
	}
}
示例#4
0
func hostPublisher(clients db.Clients) {
	for sample := range hostPublishC {
		err := clients.DB.PublishHost(sample)
		if err != nil {
			lg.Error(err)
		}
	}
}
示例#5
0
文件: api.go 项目: thomasf/alkasir
func apiError(w rest.ResponseWriter, error string, code int) {
	w.WriteHeader(code)
	if lg.V(5) {
		lg.InfoDepth(1, fmt.Sprintf("%d: %s", code, error))
	}
	err := w.WriteJson(map[string]string{
		"Error": error,
		"Ok":    "false",
	})
	if err != nil {
		lg.Error(err)
		return
	}
}
示例#6
0
func sessionFetcher(clients db.Clients) {
loop:
	for token := range sessionFetchC {
		if token == "" {
			lg.Errorln("empty token received, skipping")
			continue loop

		}
		samples, err := clients.DB.GetSessionSamples(token)
		if err != nil {
			lg.Error(err)
			continue loop
		}
		sampleAnalysisC <- samples
	}
}
示例#7
0
func samplesAnalyzer() {
loop:
	for samples := range sampleAnalysisC {
		var (
			newTokenSample db.Sample
			clientSamples  = make(map[string]db.Sample, 0)
			centralSamples = make(map[string]db.Sample, 0)
		)

		// organize input data
		for _, s := range samples {
			switch s.Type {
			case "NewClientToken":
				if newTokenSample.Token != "" {
					lg.Error("got more than one newTokenSample, aborting")
					continue loop
				}
				newTokenSample = s
			case "HTTPHeader", "DNSQuery":
				switch s.Origin {
				case "Central":
					centralSamples[s.Type] = s
				case "Client":
					clientSamples[s.Type] = s
				}
			default:
				lg.Errorf("dont know how to handle %d %s, skipping", s.ID, s.Type)
			}
		}

		// validate that wanted data types are available
		if newTokenSample.Token == "" {
			lg.Errorln("No newTokenSample, aborting")
			continue loop
		}
		if !shared.AcceptedHost(newTokenSample.Host) {
			lg.Warningln("not accepted host id:", newTokenSample.ID, newTokenSample.Host)
			continue loop
		}
		for _, smap := range []map[string]db.Sample{clientSamples, centralSamples} {
			for _, stype := range []string{"HTTPHeader"} {
				if _, ok := smap[stype]; !ok {
					lg.Errorf("missing %s, cannot analyse", stype)
					continue loop
				}
			}
		}

		// parse data
		clientSample := clientSamples["HTTPHeader"]
		var clientHeader measure.HTTPHeaderResult
		centralSample := centralSamples["HTTPHeader"]
		var centralHeader measure.HTTPHeaderResult

		if err := json.Unmarshal(clientSample.Data, &clientHeader); err != nil {
			lg.Errorln(err)
			continue loop
		}
		if err := json.Unmarshal(centralSample.Data, &centralHeader); err != nil {
			lg.Error(err)
			continue loop
		}

		// score data
		score := scoreHTTPHeaders(clientHeader, centralHeader)
		lg.V(10).Infof("session:%s %s", newTokenSample.Token, score)

		if score.Score() >= 0.5 {
			lg.Infoln("publishing session", newTokenSample.Token)
			hostPublishC <- newTokenSample
		} else {
			lg.Infoln("not publishing session", newTokenSample.Token)
		}
	}
}
示例#8
0
文件: http.go 项目: thomasf/alkasir
func startInternalHTTPServer(authKey string) error {

	lg.V(15).Infoln("starting internal api server")
	mux, err := createServeMux()
	if err != nil {
		lg.Error("failed to create router")
		return err
	}

	auth := Auth{Key: authKey, wrapped: mux}
	conf := clientconfig.Get()
	listener, err := net.Listen("tcp", conf.Settings.Local.ClientBindAddr)
	if err != nil {
		lg.Warning(err)
		listener, err = net.Listen("tcp", "127.0.0.1:")
	}
	if err != nil {
		lg.Warning(err)
		ui.Notify("Could not bind any local port (bootstrap)")
		lg.Errorln("Could not bind any local port (bootstrap)")
		return err
	}

	go func(listenaddr string) {
		// baseURL := fmt.Sprintf()
		baseURL := fmt.Sprintf("http://%s?suk=", listenaddr)
		for {
			select {
			case <-ui.Actions.CopyBrowserCodeToClipboard:
				bc := browsercode.BrowserCode{Key: authKey}
				err := bc.SetHostport(listener.Addr().String())
				if err != nil {
					lg.Errorln(err)
					continue
				}
				err = bc.CopyToClipboard()
				if err != nil {
					lg.Errorln(err)
				}

			case <-ui.Actions.OpenInBrowser:
				browser.OpenURL(baseURL + singleUseKeys.New() + "#/")

			case <-ui.Actions.Help:
				browser.OpenURL(baseURL + singleUseKeys.New() + "#/docs/__/index")
			}
			singleUseKeys.Cleanup()
		}
	}(listener.Addr().String())

	doneC := make(chan bool, 1)
	go func() {
		defer listener.Close()
		err = http.Serve(listener, auth)
		if err != nil {
			doneC <- false
		}
	}()
	select {
	case ok := <-doneC:
		if !ok {
			return errors.New("Could not start internal http server")
		}
	case <-time.After(time.Millisecond * 200):
		return nil
	}
	return nil
}
示例#9
0
文件: api.go 项目: thomasf/alkasir
// Update list of blocked hosts for an IP address.
func GetHosts(dbclients db.Clients) func(w rest.ResponseWriter, r *rest.Request) {
	relh := relatedHosts{
		dbclients: dbclients,
	}
	relh.update()
	go func() {
		for range time.NewTicker(10 * time.Minute).C {
			relh.update()
		}
	}()
	return func(w rest.ResponseWriter, r *rest.Request) {

		// HANDLE USERIP BEGIN
		req := shared.UpdateHostlistRequest{}
		err := r.DecodeJsonPayload(&req)
		if err != nil {
			apiError(w, shared.SafeClean(err.Error()), http.StatusInternalServerError)
			return
		}

		// parse/validate client ip address.
		IP := req.ClientAddr
		if IP == nil {
			apiError(w, "bad ClientAddr", http.StatusBadRequest)
			return
		}

		// resolve ip to asn.
		var ASN int
		ASNres, err := dbclients.Internet.IP2ASN(IP)
		if err != nil {
			lg.Errorln(shared.SafeClean(err.Error()))
			apiError(w, shared.SafeClean(err.Error()), http.StatusInternalServerError)
			return
		}
		if ASNres != nil {
			ASN = ASNres.ASN
		} else {
			lg.Warningf("no ASN lookup result for IP: %s ", shared.SafeClean(IP.String()))
		}

		// resolve ip to country code.
		countryCode := dbclients.Maxmind.IP2CountryCode(IP)

		req.ClientAddr = net.IPv4zero
		IP = net.IPv4zero
		// HANDLE USERIP END

		hosts, err := dbclients.DB.GetBlockedHosts(countryCode, ASN)
		if err != nil {
			apiError(w, err.Error(), http.StatusInternalServerError)
			return
		}

		simpleData := struct {
			ClientVersion string `json:"version"` // client version idientifer
		}{
			req.ClientVersion,
		}
		data, err := json.Marshal(simpleData)
		if err != nil {
			lg.Errorln(err)
		}

		ss := db.SimpleSample{
			CountryCode: countryCode,
			ASN:         ASN,
			Type:        "ClientBlocklistUpdate",
			OriginID:    req.UpdateID,
			Data:        data,
		}
		err = dbclients.DB.InsertSimpleSample(ss)
		if err != nil {
			lg.Errorf("error persisting simplesample %v", ss)
		}

		err = w.WriteJson(shared.UpdateHostlistResponse{
			Hosts: relh.fill(hosts),
		})
		if err != nil {
			lg.Error(err)
			return
		}

	}
}