public async Task ProcessLogFile(int server_id)
        {
            int savecounter = 0;

            using (var streamReader = new StreamReader(Request.Body)) {
                var commonLogParser = new CommonLogFormatParser(streamReader);

                var pipeline = new AggregatedFilterPipeline();

                FlareContext context;
                while ((context = await commonLogParser.ParseSingle()) != null)
                {
                    var flaggableContext = new FlaggableFlareContext(context);
                    await pipeline.ProcessRequest(flaggableContext);

                    var ip = await geoIpService.Query(flaggableContext.Context.request.ip);

                    db.requests.Add(new request {
                        server_id            = server_id,
                        ip_id                = ip.id,
                        request_identity     = context.request.identity,
                        request_user_id      = context.request.userid,
                        request_date         = context.request.date,
                        request_method       = context.request.method,
                        request_path         = context.request.path,
                        request_query_string = context.request.query_string,
                        request_http_version = context.request.http_version,
                        response_code        = context.response?.status_code,
                        response_length      = context.response?.bytes_sent,
                        flags                = flaggableContext.Flags
                    });

                    if (++savecounter % 4000 == 0)
                    {
                        await db.SaveChangesAsync();

                        savecounter = 0;
                    }
                }
            }

            await db.SaveChangesAsync();
        }
示例#2
0
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            using (var scope = app.ApplicationServices.GetRequiredService <IServiceScopeFactory>().CreateScope()) {
                scope.ServiceProvider.GetService <ApplicationDbContext>().Database.Migrate();
            }

            var pipeline = new AggregatedFilterPipeline();

            app
            .UseForwardedHeaders(new ForwardedHeadersOptions {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                KnownNetworks    = { new IPNetwork(new IPAddress(new byte[] { 127, 0, 0, 1 }), 32) }
            })
            .Use(async(context, next) => {
                var flareContext = new FlaggableFlareContext(new FlareContext()
                {
                    request = new FlareRequest()
                    {
                        date         = DateTimeOffset.Now,
                        http_version = (int)(double.Parse(context.Request.Protocol.Substring(5)) * 10),
                        identity     = "-",
                        ip           = context.Connection.RemoteIpAddress.ToString(),
                        method       = context.Request.Method,
                        path         = context.Request.Path.Value,
                        query_string = context.Request.QueryString.Value,
                        userid       = "-"
                    },
                    response = null
                });

                var domain = context.Request.Headers["host"];

                // Flare CDN logic
                if (domain != "localhost:5000" && domain != "api.flare.wtf")
                {
                    var db = context.RequestServices.GetRequiredService <ApplicationDbContext>();

                    var server = await db.servers
                                 .Where(a => a.proxy_active && a.domains.Any(b => b.domain == domain))
                                 .FirstOrDefaultAsync();

                    if (server == null)
                    {
                        context.Response.StatusCode = 404;
                        await context.Response.WriteAsync("The requested resource is not found. That's all we know.");
                        return;
                    }

                    var ip = await context.RequestServices.GetRequiredService <GeoIpService>()
                             .Query(flareContext.Context.request.ip);

                    var db_request = new request {
                        server_id            = server.id,
                        ip_id                = ip.id,
                        request_identity     = flareContext.Context.request.identity,
                        request_user_id      = flareContext.Context.request.userid,
                        request_date         = flareContext.Context.request.date,
                        request_method       = flareContext.Context.request.method,
                        request_path         = flareContext.Context.request.path,
                        request_query_string = flareContext.Context.request.query_string,
                        request_http_version = flareContext.Context.request.http_version,
                        //   response_code = flareContext.Context.response?.status_code,
                        //   response_length = flareContext.Context.response?.bytes_sent,
                        //   flags = flareContext.Flags
                    };

                    db.requests.Add(db_request);

                    if (await pipeline.ProcessRequest(flareContext) && server.proxy_block_requests)
                    {
                        await db.SaveChangesAsync();

                        db_request.response_code = 418;
                        db_request.flags         = flareContext.Flags;

                        await db.SaveChangesAsync();

                        var text =
                            $"418 - I am a teapot. Your request #{db_request.id} is failed because of security checks. Contact the website owner with this number if you think this was a mistake.";

                        db_request.response_length = text.Length;

                        context.Response.StatusCode = 418;
                        await context.Response.WriteAsync(text);
                        return;
                    }

                    db_request.flags = flareContext.Flags;

                    using (var httpClient = new HttpClient()) {
                        httpClient.DefaultRequestHeaders.Clear();
                        foreach (var header in context.Request.Headers
                                 .Where(a => !a.Key.StartsWith("X-")))
                        {
                            httpClient.DefaultRequestHeaders.Add(header.Key, header.Value.ToArray());
                        }

                        httpClient.DefaultRequestHeaders.Add("X-Forwarded-For", context.Connection.RemoteIpAddress.ToString());

                        using (var _req = new HttpRequestMessage(
                                   context.Request.Method == "GET" ? HttpMethod.Get :
                                   context.Request.Method == "POST" ? HttpMethod.Post :
                                   context.Request.Method == "DELETE" ? HttpMethod.Delete :
                                   context.Request.Method == "PUT" ? HttpMethod.Put :
                                   context.Request.Method == "PATCH" ? HttpMethod.Patch :
                                   context.Request.Method == "TRACE" ? HttpMethod.Trace :
                                   context.Request.Method == "OPTIONS" ? HttpMethod.Options : throw new Exception("invalid method")
                                   , $"http://{server.origin_ip}{context.Request.Path}{context.Request.QueryString}")) {
                            _req.Headers.Host = domain;

                            using (var response = await httpClient.SendAsync(_req)) {
                                db_request.response_code = context.Response.StatusCode = (int)response.StatusCode;

                                foreach (var header in response.Headers
                                         .Where(a => a.Key != "Transfer-Encoding"))
                                {
                                    context.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
                                }

                                foreach (var header in response.Content.Headers)
                                {
                                    context.Response.Headers.Add(header.Key, new StringValues(header.Value.ToArray()));
                                }

                                using (var streamWithProgess = new StreamWithProgress(context.Response.Body)) {
                                    await response.Content.CopyToAsync(streamWithProgess);
                                    await context.Response.Body.FlushAsync();
                                    context.Response.Body.Close();

                                    db_request.response_length = (int)streamWithProgess.bytesTotal;
                                    await db.SaveChangesAsync();
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (await pipeline.ProcessRequest(flareContext))
                    {
                        var text =
                            $"418 - I am a teapot. Your request is failed because of security checks. If you think it was a mistake contact [email protected]";

                        context.Response.StatusCode = 418;
                        await context.Response.WriteAsync(text);
                        return;
                    }

                    await next();
                }
            })
            .UseCors(policy => policy.SetPreflightMaxAge(TimeSpan.FromMinutes(10)).AllowAnyMethod().AllowAnyOrigin().AllowAnyHeader())
            .UseStaticFiles(new StaticFileOptions {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "../uploads")),
                RequestPath  = new PathString("/uploads")
            })
            .Use(async(context, next) => {
                IHttpBufferingFeature bufferingFeature = context.Features.Get <IHttpBufferingFeature>();
                bufferingFeature?.DisableRequestBuffering();
                bufferingFeature?.DisableResponseBuffering();

                try {
                    await next();
                } catch (Exception e) {
                    context.Response.StatusCode  = e is NotImplementedException ? 404 : e is UnauthorizedAccessException || e is SecurityTokenValidationException ? 401 : e is ArgumentException ? 400 : 500;
                    context.Response.ContentType = "application/json; charset=utf-8";

                    string message = "";

                    Exception x = e;
                    do
                    {
                        message += x.Message + "\r\n\r\n";
                    } while ((x = x.InnerException) != null);

                    await context.Response.WriteAsync(JsonConvert.SerializeObject(new {
                        code       = -1,
                        message    = message.Substring(0, message.Length - 4),
                        stacktrace = e.StackTrace
                    }));
                }
            })
            .Use(async(context, next) => {
                Token token     = null;
                string strToken = context.Request.Query["token"];

                if (strToken == null)
                {
                    string authorization = context.Request.Headers["Authorization"];
                    if (authorization != null)
                    {
                        if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                        {
                            strToken = authorization.Substring("Bearer ".Length).Trim();
                        }
                        else if (authorization.StartsWith("Basic "))
                        {
                            var encoding = Encoding.UTF8.GetString(Convert.FromBase64String(authorization.Substring("Basic ".Length))).Split(':');
                            if (encoding.Length != 2)
                            {
                                throw new UnauthorizedAccessException();
                            }

                            var username = encoding[0];
                            var password = encoding[1];

                            token = await personal_token_cache.GetAsync(username + ":" + password, async() => {
                                var db = context.RequestServices.GetRequiredService <ApplicationDbContext>();

                                var _code = AccountController.StringToByteArrayFastest(username);
                                var id    = new Guid(_code.ToArray());

                                var app2 = await db.pacs
                                           .Include(a => a.user)
                                           .SingleOrDefaultAsync(b => b.id == id);

                                if (app2 == null || app2.password_hash == null || !app2.password_hash.SequenceEqual(
                                        KeyDerivation.Pbkdf2(
                                            password: password,
                                            salt: app2.password_salt,
                                            iterationCount: 10000,
                                            numBytesRequested: 256 / 8,
                                            prf: KeyDerivationPrf.HMACSHA1
                                            )
                                        ))
                                {
                                    throw new UnauthorizedAccessException();
                                }

                                return(await token_cache.GetAsync(app2.user.id.ToString(), () => Task.FromResult <Token>(new UserToken(app2.user.id, app2.user.name, app2.user.type)), TimeSpan.FromDays(3)));
                            }, TimeSpan.FromDays(3));
                        }
                    }
                }

                if (strToken != null)
                {
                    var a = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();

                    var claims = a.ValidateToken(strToken, new TokenValidationParameters {
                        ValidateAudience = true,
                        ValidIssuer      = "Flare",
                        ValidAudience    = "Flare Users",
                        IssuerSigningKey = _key
                    }, out SecurityToken _);

                    context.User = claims;

                    var strID = context.User?.Claims?.FirstOrDefault(b => b.Type == "user_id")?.Value;
                    if (Int32.TryParse(strID, out int dwID))
                    {
                        token = await token_cache.GetAsync(strID, async() => {
                            var db   = context.RequestServices.GetRequiredService <ApplicationDbContext>();
                            var app2 = await db.users.SingleAsync(b => b.id == dwID);

                            return(new UserToken(app2.id, app2.name, app2.type));
                        }, TimeSpan.FromDays(3));
                    }
                }

                context.AddScoped(() => {
                    if (token == null)
                    {
                        throw new UnauthorizedAccessException();
                    }

                    return(token);
                });

                await next();
            })
            .UseMvc();
        }