コード例 #1
0
        public IActionResult Manage(string name, string task)
        {
            if (Defaults.ValidServices.Any(s => name == s) &&
                Defaults.ValidActions.Any(s => task == s))
            {
                if (task.Equals("config"))
                {
                    var type   = Utility.GetServiceType(name);
                    var config = _serviceConfigManager.Generate(type);
                    _response.Result = config;
                    return(Ok(_response));
                }

                var message = _serviceManager.Process(name, task, out var error);

                if (error != null)
                {
                    _response.Errors.Add(message, error);
                    return(StatusCode(500, _response));
                }

                _response.Message = message;
                return(Ok(_response));
            }

            _response.Errors.Add(Errors.INVALID_SERVICE_OR_ACTION_ATTEMPT, "");
            return(BadRequest(_response));
        }
コード例 #2
0
        private static void ValidateDaemonStartup()
        {
            var marker = Utility.GetCurrentStartupMarker();

            if (File.Exists(marker))
            {
                throw new Exception($"Spectero Daemon currently seems to be starting up, and is not ready to service requests yet (marker: {marker}). Please try again later.");
            }
        }
コード例 #3
0
        public async Task <IActionResult> GetLocalIPs()
        {
            var ips       = Utility.GetLocalIPs(AppConfig.IgnoreRFC1918);
            var addresses = ips.Select(ip => ip.ToString()).ToList();

            if (addresses.Count == 0)
            {
                var ip = await _outgoingIpResolver.Resolve();

                addresses.Add(ip.ToString());
            }

            _response.Result = addresses;
            return(Ok(_response));
        }
コード例 #4
0
        public async Task <IActionResult> HandleHttpProxyConfigUpdate([FromBody] HTTPConfig config)
        {
            if (!ModelState.IsValid || config.listeners.IsNullOrEmpty())
            {
                // ModelState takes care of checking if the field map succeeded. This means mode | allowed.d | banned.d do not need manual checking
                _response.Errors.Add(Errors.MISSING_BODY, "");
                return(BadRequest(_response));
            }

            var currentConfig = (HTTPConfig)_serviceConfigManager.Generate(Utility.GetServiceType("HTTPProxy")).First();

            var localAvailableIPs = Utility.GetLocalIPs();
            var availableIPs      = localAvailableIPs as IPAddress[] ?? localAvailableIPs.ToArray();

            var consumedListenerMap = new Dictionary <int, List <IPAddress> >();

            // Check if all listeners are valid
            foreach (var listener in config.listeners)
            {
                if (IPAddress.TryParse(listener.Item1, out var holder))
                {
                    var ipChecked   = AppConfig.BindToUnbound || availableIPs.Contains(holder) || holder.Equals(IPAddress.Any);
                    var portChecked = listener.Item2 > 1023 && listener.Item2 < 65535;

                    consumedListenerMap.TryGetValue(listener.Item2, out var existingListOfAddresses);

                    // DAEM-58 compliance: prevent unicast.any listeners if port is not entirely free.
                    if (existingListOfAddresses != null)
                    {
                        foreach (var ipAddress in existingListOfAddresses)
                        {
                            if (ipAddress.Equals(IPAddress.Any))
                            {
                                _response.Errors.Add(Errors.PORT_CONFLICT_FOUND, "0.0.0.0");
                                break;
                            }

                            // Duplicate listener found
                            if (ipAddress.Equals(holder))
                            {
                                _response.Errors.Add(Errors.DUPLICATE_IP_AS_LISTENER_REQUEST, listener.Item1);
                                break;
                            }
                        }
                    }

                    if (!ipChecked)
                    {
                        _response.Errors.Add(Errors.INVALID_IP_AS_LISTENER_REQUEST, listener.Item1);
                        break;
                    }


                    if (!portChecked)
                    {
                        _response.Errors.Add(Errors.INVALID_PORT_AS_LISTENER_REQUEST, listener.Item2);
                        break;
                    }

                    if (existingListOfAddresses == null)
                    {
                        existingListOfAddresses = new List <IPAddress>();

                        // If it was null, that means it wasn't in the dict either.
                        consumedListenerMap.Add(listener.Item2, existingListOfAddresses);
                    }

                    // List is guaranteed not null at this stage, add the IP to it.
                    existingListOfAddresses.Add(holder);
                }
                else
                {
                    _response.Errors.Add(Errors.MALFORMED_IP_AS_LISTENER_REQUEST, listener.Item1);
                    break;
                }
            }

            if (HasErrors())
            {
                Logger.LogError("CCHH: Invalid listener request found.");
                return(BadRequest(_response));
            }

            if (config.listeners != currentConfig.listeners ||
                config.proxyMode != currentConfig.proxyMode ||
                config.allowedDomains != currentConfig.allowedDomains ||
                config.bannedDomains != currentConfig.bannedDomains)
            {
                // A difference was found between the running config and the candidate config
                // If listener config changed AND service is running, the service needs restarting as it can't be adjusted without the sockets being re-initialized.
                var service       = _serviceManager.GetService(typeof(HTTPProxy));
                var restartNeeded = !config.listeners.SequenceEqual(currentConfig.listeners) && service.GetState() == ServiceState.Running;

                //Update the running config, listener config will not apply until a full system restart is made.
                service.SetConfig(new List <IServiceConfig> {
                    config
                }, restartNeeded);

                if (restartNeeded)
                {
                    _response.Message = Messages.SERVICE_RESTART_NEEDED;
                }
            }

            // If we get to this point, it means the candidate config was valid and should be committed into the DB.

            var dbConfig = await Db.SingleAsync <Configuration>(x => x.Key == ConfigKeys.HttpConfig);

            dbConfig.Value = JsonConvert.SerializeObject(config);
            await Db.UpdateAsync(dbConfig);

            _response.Result = config;
            return(Ok(_response));
        }
コード例 #5
0
ファイル: Startup.cs プロジェクト: Wintereise/spectero-daemon
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IOptionsMonitor <AppConfig> configMonitor, IApplicationBuilder app,
                              IHostingEnvironment env, ILoggerFactory loggerFactory,
                              IMigration migration, IAutoStarter autoStarter,
                              IServiceProvider serviceProvider, IApplicationLifetime applicationLifetime,
                              ILifetimeHandler lifetimeHandler)
        {
            // Create the filesystem marker that says Startup is now underway.
            // This is removed in LifetimeHandler once init finishes.
            // And yeah, the logging context is NOT yet available -_-
            if (!Utility.ManageStartupMarker())
            {
                Console.WriteLine($"ERROR: The startup marker ({Utility.GetCurrentStartupMarker()}) could NOT be created.");
            }

            var appConfig = configMonitor.CurrentValue;

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseCors("DefaultCORSPolicy");
                app.UseInterceptOptions(); // Return 200/OK with correct CORS to allow preflight requests, giant hack.
            }

            app.UseSpecteroErrorHandler();

            app.UseAddRequestIdHeader();

            // This HAS TO BE before the AddMVC call. Route registration fails otherwise.
            var option =
                new BackgroundJobServerOptions
            {
                WorkerCount = 1
            };     // Limited by SQLite, can't deal with concurrency welp.

            app.UseHangfireServer(option);
            app.UseHangfireDashboard($"/jobs");

            app.UseMvc();

            // Initialize Nlog
            loggerFactory.AddNLog();
            loggerFactory.ConfigureNLog(appConfig.LoggingConfig);
            app.AddNLogWeb();

            migration.Up();
            autoStarter.Startup();

            foreach (var implementer in serviceProvider.GetServices <IJob>())
            {
                if (!implementer.IsEnabled())
                {
                    continue;
                }

                // Magic, autowiring is magic.
                RecurringJob.AddOrUpdate(implementer.GetType().ToString(), () => implementer.Perform(),
                                         implementer.GetSchedule);
            }

            applicationLifetime.ApplicationStarted.Register(lifetimeHandler.OnStarted);
            applicationLifetime.ApplicationStopping.Register(lifetimeHandler.OnStopping);
            applicationLifetime.ApplicationStopped.Register(lifetimeHandler.OnStopped);
        }