From f4560124c24b59e0660fcdc118bef584b9a2c500 Mon Sep 17 00:00:00 2001 From: GZTime Date: Mon, 7 Aug 2023 12:40:41 +0800 Subject: [PATCH] feat(proxy): use XFF middleware in aspnetcore --- docs/pages/config/appsettings.zh.mdx | 103 +++++++++++++---------- src/GZCTF/Middlewares/ProxyMiddleware.cs | 21 ----- src/GZCTF/Program.cs | 4 +- 3 files changed, 61 insertions(+), 67 deletions(-) delete mode 100644 src/GZCTF/Middlewares/ProxyMiddleware.cs diff --git a/docs/pages/config/appsettings.zh.mdx b/docs/pages/config/appsettings.zh.mdx index 606e14325..f8cc16c4a 100644 --- a/docs/pages/config/appsettings.zh.mdx +++ b/docs/pages/config/appsettings.zh.mdx @@ -14,67 +14,71 @@ import { Callout } from "nextra-theme-docs"; 此处给出一个完整的配置文件示例: -```json5 +```json { - AllowedHosts: "*", - ConnectionStrings: { - Database: "Host=db:5432;Database=gzctf;Username=postgres;Password=", + "AllowedHosts": "*", + "ConnectionStrings": { + "Database": "Host=db:5432;Database=gzctf;Username=postgres;Password=" // redis is optional //"RedisCache": "cache:6379,password=" }, - Logging: { - LogLevel: { - Default: "Information", - Microsoft: "Warning", - "Microsoft.Hosting.Lifetime": "Information", - }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } }, - EmailConfig: { - SendMailAddress: "a@a.com", - UserName: "", - Password: "", - Smtp: { - Host: "localhost", - Port: 587, - }, + "EmailConfig": { + "SendMailAddress": "a@a.com", + "UserName": "", + "Password": "", + "Smtp": { + "Host": "localhost", + "Port": 587 + } }, - XorKey: "", - ContainerProvider: { - Type: "Docker", // or "Kubernetes" - PublicEntry: "ctf.example.com", // or "xxx.xxx.xxx.xxx" - DockerConfig: { + "XorKey": "", + "ContainerProvider": { + "Type": "Docker", // or "Kubernetes" + "PublicEntry": "ctf.example.com", // or "xxx.xxx.xxx.xxx" + "DockerConfig": { // optional - SwarmMode: false, - Uri: "unix:///var/run/docker.sock", + "SwarmMode": false, + "Uri": "unix:///var/run/docker.sock" }, - K8sConfig: { + "K8sConfig": { // optional - Namespace: "gzctf-challenges", - ConfigPath: "k8sconfig.yaml", - AllowCIDR: [ + "Namespace": "gzctf-challenges", + "ConfigPath": "k8sconfig.yaml", + "AllowCIDR": [ // allow the cluster CIDR for LB - "10.0.0.0/8", + "10.0.0.0/8" ], - DNS: [ + "DNS": [ // custom DNS to avoid cluster DNS "8.8.8.8", - "223.5.5.5", - ], - }, + "223.5.5.5" + ] + } }, - RequestLogging: false, - DisableRateLimit: false, - RegistryConfig: { - UserName: "", - Password: "", - ServerAddress: "", + "RequestLogging": false, + "DisableRateLimit": false, + "RegistryConfig": { + "UserName": "", + "Password": "", + "ServerAddress": "" }, - GoogleRecaptcha: { - VerifyAPIAddress: "https://www.recaptcha.net/recaptcha/api/siteverify", - Sitekey: "", - Secretkey: "", - RecaptchaThreshold: "0.5", + "GoogleRecaptcha": { + "VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify", + "Sitekey": "", + "Secretkey": "", + "RecaptchaThreshold": "0.5" }, + "ForwardedHeadersOptions": { + "ForwardLimit": 1, + "ForwardedForHeaderName": "X-Forwarded-For" + } } ``` @@ -178,3 +182,12 @@ GZCTF 仅支持 PostgreSQL 作为数据库,不支持 MySQL 等其他数据库 - **Sitekey:** Google Recaptcha 站点密钥 - **Secretkey:** Google Recaptcha 服务器密钥 - **RecaptchaThreshold:** Google Recaptcha 阈值,用于判断验证码是否有效 + +### ForwardedHeadersOptions + +此处配置反向代理的相关信息,用于获取真实 IP 地址,可选项。 + +- **ForwardLimit:** 反向代理层数限制 +- **ForwardedForHeaderName:** 反向代理 IP 地址头名称 + +其他字段请参考官方文档描述:[配置 ASP.NET Core 以使用代理服务器和负载均衡器](https://learn.microsoft.com/zh-cn/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-7.0) 及 [ForwardedHeadersOptions 类](https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.forwardedheadersoptions?view=aspnetcore-7.0) diff --git a/src/GZCTF/Middlewares/ProxyMiddleware.cs b/src/GZCTF/Middlewares/ProxyMiddleware.cs deleted file mode 100644 index 2e51c59be..000000000 --- a/src/GZCTF/Middlewares/ProxyMiddleware.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Net; - -namespace GZCTF.Middlewares; - -public class ProxyMiddleware -{ - private readonly RequestDelegate _next; - - public ProxyMiddleware(RequestDelegate next) => _next = next; - - public Task Invoke(HttpContext context) - { - var headers = context.Request.Headers; - if (headers.TryGetValue("X-Forwarded-For", out var value)) - { - var ipAddresses = value.ToString().Split(',', StringSplitOptions.RemoveEmptyEntries); - context.Connection.RemoteIpAddress = IPAddress.Parse(ipAddresses.FirstOrDefault() ?? "0.0.0.0"); - } - return _next(context); - } -} diff --git a/src/GZCTF/Program.cs b/src/GZCTF/Program.cs index e455eee8c..272e229a0 100644 --- a/src/GZCTF/Program.cs +++ b/src/GZCTF/Program.cs @@ -12,6 +12,7 @@ using GZCTF.Services.Interface; using GZCTF.Utils; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.ResponseCompression; @@ -185,6 +186,7 @@ builder.Services.Configure(builder.Configuration.GetSection(nameof(GlobalConfig))); builder.Services.Configure(builder.Configuration.GetSection(nameof(GamePolicy))); builder.Services.Configure(builder.Configuration.GetSection(nameof(ContainerProvider))); +builder.Services.Configure(builder.Configuration.GetSection(nameof(ForwardedHeadersOptions))); if (builder.Configuration.GetSection(nameof(ContainerProvider)) .GetValue(nameof(ContainerProvider.Type)) @@ -263,7 +265,7 @@ } }); -app.UseMiddleware(); +app.UseForwardedHeaders(); app.UseRouting();