VKProxy 目前新添加了如下功能
- 会话亲和性
- 禁止http
- 静态内容
- 简单的waf
VKProxy 是使用c#开发的基于 Kestrel 实现 L4/L7的代理(感兴趣的同学烦请点个github小赞赞呢)
会话亲和性
会话亲和性是一种机制,用于将有因果关系的请求序列绑定到在多个目标之间均衡负载时处理第一个请求的目标。 在序列中的大多数请求处理相同数据以及处理请求的不同节点(目标)的数据访问成本不同的情况下,它很有用。 最常见的示例是暂时性缓存(例如内存中),其中第一个请求将数据从较慢的永久性存储提取到快速本地缓存中,而其他请求则只处理缓存的数据,从而增加吞吐量。
建立新的亲和性或解析现有的亲和性
请求到达并路由到启用了会话亲和性的群集后,代理会根据请求中的亲和性键的状态和有效性来自动决定是应建立新的亲和性,还是需要解析现有的亲和性,如下所示:
-
请求不包含密钥。 跳过解析,并与负载均衡器选择的目标建立新的亲和性
-
请求中已找到关联密钥,并且有效. 相关性机制会尝试查找与密钥匹配的第一个正常目标。
-
关联键无效或找不到正常健康的关联目标。 它被视为失败,并与负载均衡器选择的目标建立新的亲和性
如果为请求建立了新的相关性,则关联键会附加到响应,其中确切的键表示形式和位置取决于实现。 目前,有两个内置策略将密钥存储在cookie标头或自定义标头上。 将响应传递到客户端后,客户端负责将密钥附加到同一会话中的所有以下请求。 此外,当承载密钥的下一个请求到达代理时,它会解析现有相关性,但关联密钥不会再次附加到响应。 因此,只有第一个响应具有亲和性键。
有四种内置关联策略,这些策略在请求和响应上以不同的方式格式化和存储密钥。
-
HashCookie
策略使用 XxHash64 哈希为 cookie 值生成快速、紧凑、不明确的输出格式。
请求的键将作为具有配置名称的 cookie 进行传递,并在关联序列中的第一个响应上使用 cookie 标头设置相同的 Set-Cookie。
-
ArrCookie
策略使用 SHA-256 哈希为cookie值生成模糊输出。
请求的键将作为具有配置名称的 cookie 进行传递,并在关联序列中的第一个响应上使用 cookie 标头设置相同的 Set-Cookie。
-
Cookie
策略使用数据保护来加密密钥
请求的键将作为具有配置名称的 cookie 进行传递,并在关联序列中的第一个响应上使用 cookie 标头设置相同的 Set-Cookie。
-
CustomHeader
策略使用数据保护来加密密钥,将密钥存储为加密标头。 它要求在具有已配置名称的自定义标头中传递关联键,并在关联序列中的第一个响应上设置相同的标头。
由于 header 不具备 cookie 这般在浏览器等有内置附加在请求处理的逻辑,需要用户自行处理附加在后续的请求中。所以优先使用 cookie的方式
设置项
大家可以可以在cluster的Metadata
设置SessionAffinity
为 HashCookie/ArrCookie/Cookie/CustomHeader
其一来启用会话亲和性
-
CustomHeader
当
SessionAffinityKey
有设置时,其值将作为 header name,否则将默认采用x-sessionaffinity
-
HashCookie/ArrCookie/Cookie
当
SessionAffinityKey
有设置时,其值将作为 cookie name,否则将默认采用SessionAffinity
而如下设置可以用于控制 cookie
-
CookieDomain
获取或设置要与 Cookie 关联的域。
-
CookieExpires
获取或设置 Cookie 的到期日期和时间。
-
CookieExtensions
获取要追加到 Cookie 的其他值的集合。
-
CookieHttpOnly
获取或设置一个值,该值指示客户端脚本是否无法访问 Cookie。 不设置则默认为 true
-
CookieIsEssential
指示此 Cookie 是否对应用程序正常运行至关重要。 如果为 true,则可以绕过同意策略检查。 默认值为 false。
-
CookieMaxAge
获取或设置 Cookie 的最大期限。
-
CookiePath
获取或设置 Cookie 路径。 不设置则默认为"/"
-
CookieSameSite
获取或设置 Cookie 的 SameSite 属性的值。 默认值为 Unspecified
-
CookieSecure
获取或设置一个值,该值指示是否使用安全套接字层(SSL)(即仅通过 HTTPS 传输 Cookie)。
-
配置示例:
json
{
"ReverseProxy": {
"Routes": {
"a": {
"Order": 0,
"Match": {
"Hosts": [ "api.com" ],
"Paths": [ "*" ]
},
"ClusterId": "apidemo",
"Metadata": {
"MirrorCluster": "apidemoMirror"
}
}
},
"Clusters": {
"apidemo": {
"LoadBalancingPolicy": "RoundRobin",
"Metadata": {
"SessionAffinity": "Cookie",
"CookieExpires": "00:00:13"
},
"Destinations": [
{
"Address": "https://xxx.lt"
},
{
"Address": "https://xxx1.lt"
},
{
"Address": "https://xxx2.lt"
}
]
}
}
}
}
禁止http
有一些原因需要我们禁用 HTTP(即只允许 HTTPS,不允许明文 HTTP),比如:
- 数据加密安全
HTTP 传输的数据是明文的,容易被窃听、篡改和中间人攻击。而 HTTPS 使用 TLS/SSL 加密,能保护数据在传输过程中的安全性和隐私性。
- 身份验证
HTTPS 通过证书机制可以验证服务器身份,防止被钓鱼网站冒充。HTTP 无法保证你访问的是"真实"的服务器。
- 数据完整性
通过 HTTPS 传输的数据无法被中途篡改,而 HTTP 没有任何防护,容易被劫持或修改内容。
- 合规要求
许多法律法规(如GDPR、PCI DSS等)要求必须加密用户敏感数据的传输,明文 HTTP 不符合这些合规要求。
- 浏览器政策
现代主流浏览器(如 Chrome、Firefox)对 HTTP 网站会高亮"不安全",甚至屏蔽部分功能,如获取地理位置、摄像头、麦克风等。部分浏览器或 API 也要求强制使用 HTTPS。
- SEO 优势
搜索引擎(如 Google)会优先收录和排名 HTTPS 网站,禁用 HTTP 有助于提升网站权重。
所以VKProxy 提供了非常简单的强制重定向功能
设置项
大家可以可以在cluster的Metadata
设置OnlyHttps
为 "true"
来启用
配置示例:
json
{
"ReverseProxy": {
"Routes": {
"a": {
"Order": 0,
"Match": {
"Hosts": [ "api.com" ],
"Paths": [ "*" ],
"Statement": "Header('x-env') = 'test'"
},
"ClusterId": "ClusterA",
"Metadata": {
"OnlyHttps": "true"
}
}
}
}
}
实现其实非常简单
csharp
public class OnlyHttpsFunc : IHttpFunc
{
public int Order => -1000;
public RequestDelegate Create(RouteConfig config, RequestDelegate next)
{
if (config.Metadata == null || !config.Metadata.TryGetValue("OnlyHttps", out var v) || !bool.TryParse(v, out var b) || !b) return next;
return c =>
{
if (c.Request.IsHttps)
{
return next(c);
}
else
{
c.Response.Redirect($"https://{c.Request.Host}{c.Request.GetEncodedPathAndQuery()}", true);
return c.Response.CompleteAsync();
}
};
}
}
静态内容
有很多时候我们需要临时或者不同环境添加一些不同内容,
比如 robots.txt
在开发阶段,多半不会有人考虑这东西,多半都是遇到一些问题后才会调整这些东西,但是通常这时候调整程序就显得杀鸡用牛刀了
所以 VKProxy 就提供了一个简单的功能,可以随时添加一些静态响应内容
设置项
大家可以可以在cluster的Metadata
设置
-
xxx_Content
xxx 可以任意命名,只要不重复就好
内容即为响应body
-
xxx_ContentType
xxx_Content 对应的 ContentType, 不设置默认为
text/plain
-
xxx_ContentWhen
xxx_Content 对应的 条件筛选 比如
Path = '/robots.txt'
意味着只有url为 /robots.txt才能匹配,具体配置可参考如何为HTTP配置路由复杂匹配
配置示例:
json
{
"ReverseProxy": {
"Routes": {
"a": {
"Order": 0,
"Match": {
"Hosts": [ "*.com" ],
"Paths": [ "*" ]
},
"ClusterId": "ClusterA",
"Metadata": {
"robots_Content": "User-agent: \r\n*Allow: /\r\nSitemap: https://www.xxx.com/sitemap.xml",
"robots_ContentType": "application/text",
"robots_ContentWhen": "Path = '/robots.txt'"
}
}
}
}
}
简单的waf
WAF 是一种专门用于保护 Web 应用程序的安全防护。它通过检测、过滤和拦截进出 Web 应用的 HTTP/HTTPS 流量,防止常见的 Web 攻击,比如:
- SQL 注入(SQL Injection)
- 跨站脚本攻击(XSS, Cross-Site Scripting)
- 文件包含漏洞
- 远程命令执行
- 等等
VKProxy 肯定无法做到专业级别的防护(毕竟俺不是吃这一口饭的,没必要没钱还去撞个头破血流),只提供基本功能:用户可以设置基本的匹配规则限制相应的请求。
这样没钱没精力的用户可以优先不修改程序的场景临时做一些简单的处理,
比如 wordpress 搭建的站点都有管理页面 yourdomain.com/wp-admin, 你并不想暴露这些地址到外网
设置项
大家可以可以在cluster的Metadata
设置
-
xxx_waf
xxx 可以任意命名,只要不重复就好
配置内容即为条件筛选 比如
Path = '/robots.txt'
意味着只有url为 /robots.txt才能匹配,具体配置可参考如何为HTTP配置路由复杂匹配只有匹配就会直接返回 403, 不再转发到后端服务器
配置示例:
json
{
"ReverseProxy": {
"Routes": {
"a": {
"Order": 0,
"Match": {
"Hosts": [ "*.com" ],
"Paths": [ "*" ]
},
"ClusterId": "ClusterA",
"Metadata": {
"noadmin_waf": "Path = '/wp-admin'"
}
}
}
}
}
VKProxy 是使用c#开发的基于 Kestrel 实现 L4/L7的代理(感兴趣的同学烦请点个github小赞赞呢)