VKProxy 是使用c#开发的基于 Kestrel 实现 L4/L7的代理

有兴趣的同学点个赞呗

目前已经在写文档了, 文档在 https://fs7744.github.io/VKProxy.Doc/docs/introduction.html (未完成全部)

UI配置站点也在开发ing了,会基于 etcd 作为配置源,主要考虑配置文件分发会导致大家在部署多实例场景有难度

docker 会在 UI配置站点 完成后再完善到文档

这里列举一下基本的配置

安装

自行构建

VKProxy 有很多扩展点可以定制化大家所需特制化需求,所以有相关需求时推荐自行构建

创建一个项目,然后选取所需package安装

dotnet add package VKProxy
dotnet add package VKProxy.Storages.Etcd

配置程序

using Microsoft.Extensions.Hosting;
using ProxyDemo; var app = Host.CreateDefaultBuilder(args)
.UseReverseProxy()
.ConfigureServices(i =>
{
// 默认加载appsettings.json 配置
// 如需采用 etcd 作为配置源,请设置环境变量`ETCD_CONNECTION_STRING`并使用如下代码
// i.UseEtcdConfigFromEnv();
})
.Build(); await app.RunAsync();

配置代理

假如使用 appsettings.json 进行配置, 这里列举一个http1的代理配置

(配置项很多,可参考后续具体配置项说明, 也可以考虑使用 UI配置站点)

{
"ReverseProxy": {
// 监听端口 127.0.0.1:5001
"Listen": {
"http": {
"Protocols": [
"Http1"
],
"Address": [
"127.0.0.1:5001"
]
}
},
// 设置路由匹配任意 com 结尾的host,以及 url开头为 /ws 并且 method 为 GET的请求
"Routes": {
"HTTPTEST": {
"Match": {
"Hosts": [
"*com"
],
"Paths": [
"/ws*"
],
"Statement": "Method = 'GET'"
},
"ClusterId": "apidemo",
"Timeout": "00:10:11"
}
},
// 配置匹配请求转发到对应目标地址,并且通过主动健康检查保证服务稳定
"Clusters": {
"apidemo": {
"LoadBalancingPolicy": "RoundRobin",
"HealthCheck": {
"Active": {
"Enable": true,
"Policy": "Http",
"Path": "/test",
"Query": "?a=d",
"Method": "post"
}
},
"Destinations": [
{
"Address": "http://127.0.0.1:1104"
},
{
"Address": "https://google.com"
}
]
}
}
}
}

不同监听场景如何配置

[!WARNING]

虽然可以在运行时动态变更监听,但是目前Kestrel在终止监听时会等待已有连接结束,以降低对用户影响,达到优雅关闭的效果

所以在动态变更时不一定能实时生效,一定会等待已访问连接结束(超时时间1秒,超时将强制关闭),如果频繁变化,可能会导致问题

监听 UDP

这里展示如何 将 127.0.0.1:5000 UDP 代理到 127.0.0.1:11000, 同时只接受服务端最多返回一个 udp 包

{
"ReverseProxy": {
"Listen": {
// Listen id : udptest
"udptest": {
"Protocols": [ "UDP" ], // 协议选择 UDP
"Address": [ "127.0.0.1:5000" ], // 监听地址
"RouteId": "udpTestRoute" // UDP 必填路由,因为不像http 有host等协议参数能确定目的地址
}
},
"Routes": {
// Routes id : udpTestRoute
"udpTestRoute": {
"ClusterId": "udpTestCluster", // udp 目的地址 id
"UdpResponses": 1, // 只接受服务端最多返回一个 udp 包
"Timeout": "00:00:11" // 超时时间 11 秒, 包含从udp包 发送到 目的地址和 等待以及返回 服务端udp包的总共时间
}
},
"Clusters": {
// Clusters id : udpTestCluster
"udpTestCluster": {
"Destinations": [
{
"Address": "127.0.0.1:11000" //目的地址
}
]
}
}
}
}

监听 TCP

这里展示如何 将 127.0.0.1:5000 TCP 代理到 https://google.com

{
"ReverseProxy": {
"Listen": {
// Listen id : tcpTest
"tcpTest": {
"Protocols": [ "TCP" ], // 协议选择 TCP
"Address": [ "127.0.0.1:5000" ], // 监听地址
"RouteId": "tcpTestRoute" // tcp 必填路由,因为不像http 有host等协议参数能确定目的地址
}
},
"Routes": {
// Routes id : tcpTestRoute
"tcpTestRoute": {
"ClusterId": "tcpTestCluster", // tcp 目的地址 id
"Timeout": "00:00:11" // 超时时间 11 秒,
}
},
"Clusters": {
// Clusters id : tcpTestCluster
"tcpTestCluster": {
"Destinations": [
{
"Address": "https://google.com" //目的地址
}
]
}
}
}
}

监听 SNI 代理 (Passthrough)

这里展示如何 将 127.0.0.1:5000 TCP SNI

并通过ssl握手时的 host 路由匹配代理到 https://google.com, 但这里我们配置不在proxy端处理ssl,而是交由后端服务自行处理

{
"ReverseProxy": {
"Listen": {
// Listen id : tcpTest
"tcpTest": {
"Protocols": [
"TCP"
], // 协议选择 TCP
"Address": [
"127.0.0.1:5000"
], // 监听地址
"UseSni": true // 开启 sni 代理,由于采用 公用 sni ,所以不必配置RouteId
}
},
"Sni": {
"sniPassthroughTest": {
// 这里配置 所有 com 结尾的请求都会路由到 tcpTestRoute
"Host": [
"*com"
],
"Passthrough": true, // 配置不在proxy端处理ssl,而是交由后端服务自行处理
"RouteId": "tcpTestRoute"
},
},
"Routes": {
// Routes id : tcpTestRoute
"tcpTestRoute": {
"ClusterId": "tcpTestCluster", // tcp 目的地址 id
"Timeout": "00:00:11" // 超时时间 11 秒,
}
},
"Clusters": {
// Clusters id : tcpTestCluster
"tcpTestCluster": {
"Destinations": [
{
"Address": "https://google.com" //目的地址
}
]
}
}
}
}

监听 SNI 代理 (ssl)

这里展示如何 将 127.0.0.1:5000 TCP SNI

并通过ssl握手时的 host 路由匹配代理到 http://google.com, 但这里我们配置在proxy端处理ssl,并且由于是tcp代理,所以后端服务无法使用 https, 因为已经被proxy 解密了,http请求的场景只能配置后端服务为 http了

{
"ReverseProxy": {
"Listen": {
// Listen id : tcpTest
"tcpTest": {
"Protocols": [
"TCP"
], // 协议选择 TCP
"Address": [
"127.0.0.1:5000"
], // 监听地址
"UseSni": true // 开启 sni 代理,由于采用 公用 sni ,所以不必配置RouteId
}
},
"Sni": {
"sniPassthroughTest": {
// 这里配置 所有 com 结尾的请求都会路由到 tcpTestRoute
"Host": [
"*com"
],
"CheckCertificateRevocation": false, // 不进行证书校验, 因为这里配置的是自签证书,只是用于测试
// 这里配置 PEM 格式证书, 这样配置便于更换,如果使用机器上的证书文件,有一些场景比如 docker 大家就很不方便了
"Certificate": {
"PEM": "-----BEGIN CERTIFICATE-----\nMIIFCzCCAvOgAwIBAgIUAi7DqcEn4EsBm1lN4UcmmuxWPq0wDQYJKoZIhvcNAQEL\nBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIxMDIyNjE4MzI0OVoYDzIxMjEw\nMjAyMTgzMjQ5WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEB\nAQUAA4ICDwAwggIKAoICAQDI5+DbDLpVmRFFB9YR1NwAbdPzf7cV8RB32pNVHzLj\niJ9LNSq8yvI/k6xD3p8XHVJEC3TGMuOVK4Cn277nX9KSU/7lELMlz+yGikwli3aI\nu4A7NE84ACfR6ZFelAGcGr2nMze6K2YDwhhqG8SUBIhAjzjIXSf2+cv0Cq38cEX1\nWKy1h5xJm7FwuKlZsHmJw5Osk+8mFgHJ5TmKqJYtVd7b/ytAmeM2ByZ4eVCZ31rR\nELKZ2uEWoCImLCtCfohxEnhrLm09yB7JrbbT/3JXHXyQUn3kGMczgwL/IZZwqtAf\nE4SiHVLI3cFwO3VJjpRfAbg3xFbxwzhmdlri3WsKT3iEp3P08WPi6dL7WF+PjpMl\nd9RZ587NBSqCmVfgBjY05wEcONSPyPY1gi5ZBDBm6J23feAOgZ8AZu/RKdAVgYBu\nKr6o6ZKqsJ+U+M5cwrXw/Rv78YQyr9ZlfKALbybMKMrYuc9DqbPGBbryLxklh9kN\nwMJvt8FHEcmlbT5BsZJmm7JztPouN7mxMy1ZVJlGreyPD0mxET+O4DCz7UsA2CvB\npKzLcRRHKKNbCwaeV/1UJKiyg4QWDGltlIKkIEhppv2vspl0Gh7xpZISJuWtmWiJ\no03zSr7NUNvXRY3pmNQXad7PHanVyTCopCCpTiAQljDTTb803NGyKBHx3cz17HU9\nxQIDAQABo1MwUTAdBgNVHQ4EFgQUGyQOi+8yPBZziF7ruCfQB4ooTMUwHwYDVR0j\nBBgwFoAUGyQOi+8yPBZziF7ruCfQB4ooTMUwDwYDVR0TAQH/BAUwAwEB/zANBgkq\nhkiG9w0BAQsFAAOCAgEAHf+FN6rHdZJPdmUO1skpS9iVgXrKWGwo20Qrd3MttKfk\nxzFpOZLBEyn/qWmZe1YQqdcm4Yd7OjnKRb62zwE8gyTJlaA30qXGoJZrouWEAsWZ\n2//2h/Ju6XNy47p5F2UKAKqqGcSaDy9HEQF0wNwRz45LKYlJE7v7eDqo2TOampoH\nUXNRF9lKI4o+CKkSRquoqGXfw6GJmnxrozTzWl00igSXrX3+HkiKHNOgzaOoS+pP\nnFl/HI/jOFYh8AG/18U5iFBSTjXiyXmFvkb4309c188fJd1UMOVY1tbcfFWSftnL\nYbk8UmGagtI9S8ExuQvk34TGDwj0vdKGiTBdL/qQ1vzxqLo2U7fHRcktSo27Ogtp\nJCzfyXKb41Cu4VOmzllTlhbg/p68rEeYcVIeZl86Yh3bFZNVpvHW9vzn8iLIXpGf\nnyt/XXG0cgkTPeWZ+zTPHLx/9YZBXViUuXobXLeUhueCaWGHYPkzKcV1c1B9oJjc\n/3JWbJVERFxMGgJpQUrTMerUCmY3C2lfPBm48ZmPCjmUUdWsh5vu2pVe+3hBIFeb\nY/kkOuRqAmiW+EmjFNQNdcxsDstd1AeipapPSH0TLWTqvAs8MndoNmfHyOFomV38\nEls5LL5Pomm27oVq6JM1geF1jKShAnO/w/dlRXcB0PFJIlpWKpw7OE5qqPpoiZY=\n-----END CERTIFICATE-----",
"PEMKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\n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\nBlK3Zix8WqtE14P/MNzfaA==\n-----END ENCRYPTED PRIVATE KEY-----",
"Password": "testPassword"
},
"RouteId": "tcpTestRoute"
},
},
"Routes": {
// Routes id : tcpTestRoute
"tcpTestRoute": {
"ClusterId": "tcpTestCluster", // tcp 目的地址 id
"Timeout": "00:00:11" // 超时时间 11 秒,
}
},
"Clusters": {
// Clusters id : tcpTestCluster
"tcpTestCluster": {
"Destinations": [
{
"Address": "http://google.com" //目的地址 由于是tcp代理,所以后端服务无法使用 https, 因为已经被proxy 解密了,http请求的场景只能配置后端服务为 http了
}
]
}
}
}
}

监听 http 代理

这里展示如何 将 127.0.0.1:5000 http1 协议 ,(其他版本需要证书,所以这里单独展示配置,以便大家对比)

并通过 host 路由匹配代理到 http://google.com

{
"ReverseProxy": {
"Listen": {
// Listen id : httpTest
"httpTest": {
"Protocols": [
"HTTP1"
], // 协议选择 HTTP1
"Address": [
"127.0.0.1:5000"
], // 监听地址
},
},
"Routes": {
// Routes id : httpTestRoute
"httpTestRoute": {
// 配置 http 请求如何匹配
"Match": {
"Hosts": [ "*com" ], // 匹配 host 为 com 结尾的
"Paths": [ "/ws*" ], // url 匹配 /ws 开头的
"Statement": "Method = 'GET'" // http method 匹配 GET, 这里提供 类似 sql 中 where 的简单表达式写法,当然有一些限制,请参见 Statement 说明
},
"ClusterId": "httpTestCluster", // 目的地址 id
"Timeout": "00:00:11" // 超时时间 11 秒,
}
},
"Clusters": {
// Clusters id : httpTestCluster
"httpTestCluster": {
"Destinations": [
{
"Address": "http://google.com"
}
]
}
}
}
}

监听 https (证书通过sni匹配) 代理

这里展示如何 将 127.0.0.1:5000 http1 / http2 协议 ,证书通过sni匹配, http3 因为目前 quic 底层实现限制, 无法在运行时动态切换证书,所以无法在sni 配置

并通过 host 路由匹配代理到 http://google.com

{
"ReverseProxy": {
"Listen": {
// Listen id : httpTest
"httpTest": {
"Protocols": [
"HTTP1","HTTP2"
], // 协议选择 HTTP1 HTTP2
"Address": [
"127.0.0.1:5000"
], // 监听地址
"UseSni": true // 表明 启用 https
}
},
"Routes": {
// Routes id : httpTestRoute
"httpTestRoute": {
// 配置 http 请求如何匹配
"Match": {
"Hosts": [ "*com" ], // 匹配 host 为 com 结尾的
"Paths": [ "/ws*" ], // url 匹配 /ws 开头的
"Statement": "Method = 'GET'" // http method 匹配 GET, 这里提供 类似 sql 中 where 的简单表达式写法,当然有一些限制,请参见 Statement 说明
},
"ClusterId": "httpTestCluster", // 目的地址 id
"Timeout": "00:00:11" // 超时时间 11 秒,
}
},
"Clusters": {
// Clusters id : httpTestCluster
"httpTestCluster": {
"Destinations": [
{
"Address": "http://google.com"
}
]
}
},
"Sni": {
"sniComTest": {
// 这里配置 所有 com 结尾的SSL握手请求都会匹配到如下证书
"Host": [
"*com"
],
"CheckCertificateRevocation": false, // 不进行证书校验, 因为这里配置的是自签证书,只是用于测试
// 这里配置 PEM 格式证书, 这样配置便于更换,如果使用机器上的证书文件,有一些场景比如 docker 大家就很不方便了
"Certificate": {
"PEM": "-----BEGIN CERTIFICATE-----\nMIIFCzCCAvOgAwIBAgIUAi7DqcEn4EsBm1lN4UcmmuxWPq0wDQYJKoZIhvcNAQEL\nBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIxMDIyNjE4MzI0OVoYDzIxMjEw\nMjAyMTgzMjQ5WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEB\nAQUAA4ICDwAwggIKAoICAQDI5+DbDLpVmRFFB9YR1NwAbdPzf7cV8RB32pNVHzLj\niJ9LNSq8yvI/k6xD3p8XHVJEC3TGMuOVK4Cn277nX9KSU/7lELMlz+yGikwli3aI\nu4A7NE84ACfR6ZFelAGcGr2nMze6K2YDwhhqG8SUBIhAjzjIXSf2+cv0Cq38cEX1\nWKy1h5xJm7FwuKlZsHmJw5Osk+8mFgHJ5TmKqJYtVd7b/ytAmeM2ByZ4eVCZ31rR\nELKZ2uEWoCImLCtCfohxEnhrLm09yB7JrbbT/3JXHXyQUn3kGMczgwL/IZZwqtAf\nE4SiHVLI3cFwO3VJjpRfAbg3xFbxwzhmdlri3WsKT3iEp3P08WPi6dL7WF+PjpMl\nd9RZ587NBSqCmVfgBjY05wEcONSPyPY1gi5ZBDBm6J23feAOgZ8AZu/RKdAVgYBu\nKr6o6ZKqsJ+U+M5cwrXw/Rv78YQyr9ZlfKALbybMKMrYuc9DqbPGBbryLxklh9kN\nwMJvt8FHEcmlbT5BsZJmm7JztPouN7mxMy1ZVJlGreyPD0mxET+O4DCz7UsA2CvB\npKzLcRRHKKNbCwaeV/1UJKiyg4QWDGltlIKkIEhppv2vspl0Gh7xpZISJuWtmWiJ\no03zSr7NUNvXRY3pmNQXad7PHanVyTCopCCpTiAQljDTTb803NGyKBHx3cz17HU9\nxQIDAQABo1MwUTAdBgNVHQ4EFgQUGyQOi+8yPBZziF7ruCfQB4ooTMUwHwYDVR0j\nBBgwFoAUGyQOi+8yPBZziF7ruCfQB4ooTMUwDwYDVR0TAQH/BAUwAwEB/zANBgkq\nhkiG9w0BAQsFAAOCAgEAHf+FN6rHdZJPdmUO1skpS9iVgXrKWGwo20Qrd3MttKfk\nxzFpOZLBEyn/qWmZe1YQqdcm4Yd7OjnKRb62zwE8gyTJlaA30qXGoJZrouWEAsWZ\n2//2h/Ju6XNy47p5F2UKAKqqGcSaDy9HEQF0wNwRz45LKYlJE7v7eDqo2TOampoH\nUXNRF9lKI4o+CKkSRquoqGXfw6GJmnxrozTzWl00igSXrX3+HkiKHNOgzaOoS+pP\nnFl/HI/jOFYh8AG/18U5iFBSTjXiyXmFvkb4309c188fJd1UMOVY1tbcfFWSftnL\nYbk8UmGagtI9S8ExuQvk34TGDwj0vdKGiTBdL/qQ1vzxqLo2U7fHRcktSo27Ogtp\nJCzfyXKb41Cu4VOmzllTlhbg/p68rEeYcVIeZl86Yh3bFZNVpvHW9vzn8iLIXpGf\nnyt/XXG0cgkTPeWZ+zTPHLx/9YZBXViUuXobXLeUhueCaWGHYPkzKcV1c1B9oJjc\n/3JWbJVERFxMGgJpQUrTMerUCmY3C2lfPBm48ZmPCjmUUdWsh5vu2pVe+3hBIFeb\nY/kkOuRqAmiW+EmjFNQNdcxsDstd1AeipapPSH0TLWTqvAs8MndoNmfHyOFomV38\nEls5LL5Pomm27oVq6JM1geF1jKShAnO/w/dlRXcB0PFJIlpWKpw7OE5qqPpoiZY=\n-----END CERTIFICATE-----",
"PEMKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\n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\nBlK3Zix8WqtE14P/MNzfaA==\n-----END ENCRYPTED PRIVATE KEY-----",
"Password": "testPassword"
}
}
},
}
}

监听 http3 代理

这里展示如何 将 127.0.0.1:5000 http1 / http2 / http3 协议 , http3 因为目前 quic 底层实现限制, 无法在运行时动态切换证书,所以特殊指定证书配置,也因此 127.0.0.1:5000 只能匹配这一证书,无法提供sni动态匹配证书的能力

并通过 host 路由匹配代理到 http://google.com

{
"ReverseProxy": {
"Listen": {
// Listen id : httpTest
"httpTest": {
"Protocols": [
"HTTP1","HTTP2", "HTTP3"
], // 协议选择 HTTP1 HTTP2 HTTP3
"Address": [
"127.0.0.1:5000"
], // 监听地址
"UseSni": true, // 表明 启用 https,
"SniId": "sniComTest" // http3 因为目前 quic 底层实现限制, 无法在运行时动态切换证书 所以特殊指定证书配置,也因此 127.0.0.1:5000 只能匹配这一证书,无法提供sni动态匹配证书的能力
}
},
"Routes": {
// Routes id : httpTestRoute
"httpTestRoute": {
// 配置 http 请求如何匹配
"Match": {
"Hosts": [ "*com" ], // 匹配 host 为 com 结尾的
"Paths": [ "/ws*" ], // url 匹配 /ws 开头的
"Statement": "Method = 'GET'" // http method 匹配 GET, 这里提供 类似 sql 中 where 的简单表达式写法,当然有一些限制,请参见 Statement 说明
},
"ClusterId": "httpTestCluster", // 目的地址 id
"Timeout": "00:00:11" // 超时时间 11 秒,
}
},
"Clusters": {
// Clusters id : httpTestCluster
"httpTestCluster": {
"Destinations": [
{
"Address": "http://google.com"
}
]
}
},
"Sni": {
"sniComTest": {
// 这里配置 所有 com 结尾的SSL握手请求都会匹配到如下证书
"Host": [
"*com"
],
"CheckCertificateRevocation": false, // 不进行证书校验, 因为这里配置的是自签证书,只是用于测试
// 这里配置 PEM 格式证书, 这样配置便于更换,如果使用机器上的证书文件,有一些场景比如 docker 大家就很不方便了
"Certificate": {
"PEM": "-----BEGIN CERTIFICATE-----\nMIIFCzCCAvOgAwIBAgIUAi7DqcEn4EsBm1lN4UcmmuxWPq0wDQYJKoZIhvcNAQEL\nBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIxMDIyNjE4MzI0OVoYDzIxMjEw\nMjAyMTgzMjQ5WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEB\nAQUAA4ICDwAwggIKAoICAQDI5+DbDLpVmRFFB9YR1NwAbdPzf7cV8RB32pNVHzLj\niJ9LNSq8yvI/k6xD3p8XHVJEC3TGMuOVK4Cn277nX9KSU/7lELMlz+yGikwli3aI\nu4A7NE84ACfR6ZFelAGcGr2nMze6K2YDwhhqG8SUBIhAjzjIXSf2+cv0Cq38cEX1\nWKy1h5xJm7FwuKlZsHmJw5Osk+8mFgHJ5TmKqJYtVd7b/ytAmeM2ByZ4eVCZ31rR\nELKZ2uEWoCImLCtCfohxEnhrLm09yB7JrbbT/3JXHXyQUn3kGMczgwL/IZZwqtAf\nE4SiHVLI3cFwO3VJjpRfAbg3xFbxwzhmdlri3WsKT3iEp3P08WPi6dL7WF+PjpMl\nd9RZ587NBSqCmVfgBjY05wEcONSPyPY1gi5ZBDBm6J23feAOgZ8AZu/RKdAVgYBu\nKr6o6ZKqsJ+U+M5cwrXw/Rv78YQyr9ZlfKALbybMKMrYuc9DqbPGBbryLxklh9kN\nwMJvt8FHEcmlbT5BsZJmm7JztPouN7mxMy1ZVJlGreyPD0mxET+O4DCz7UsA2CvB\npKzLcRRHKKNbCwaeV/1UJKiyg4QWDGltlIKkIEhppv2vspl0Gh7xpZISJuWtmWiJ\no03zSr7NUNvXRY3pmNQXad7PHanVyTCopCCpTiAQljDTTb803NGyKBHx3cz17HU9\nxQIDAQABo1MwUTAdBgNVHQ4EFgQUGyQOi+8yPBZziF7ruCfQB4ooTMUwHwYDVR0j\nBBgwFoAUGyQOi+8yPBZziF7ruCfQB4ooTMUwDwYDVR0TAQH/BAUwAwEB/zANBgkq\nhkiG9w0BAQsFAAOCAgEAHf+FN6rHdZJPdmUO1skpS9iVgXrKWGwo20Qrd3MttKfk\nxzFpOZLBEyn/qWmZe1YQqdcm4Yd7OjnKRb62zwE8gyTJlaA30qXGoJZrouWEAsWZ\n2//2h/Ju6XNy47p5F2UKAKqqGcSaDy9HEQF0wNwRz45LKYlJE7v7eDqo2TOampoH\nUXNRF9lKI4o+CKkSRquoqGXfw6GJmnxrozTzWl00igSXrX3+HkiKHNOgzaOoS+pP\nnFl/HI/jOFYh8AG/18U5iFBSTjXiyXmFvkb4309c188fJd1UMOVY1tbcfFWSftnL\nYbk8UmGagtI9S8ExuQvk34TGDwj0vdKGiTBdL/qQ1vzxqLo2U7fHRcktSo27Ogtp\nJCzfyXKb41Cu4VOmzllTlhbg/p68rEeYcVIeZl86Yh3bFZNVpvHW9vzn8iLIXpGf\nnyt/XXG0cgkTPeWZ+zTPHLx/9YZBXViUuXobXLeUhueCaWGHYPkzKcV1c1B9oJjc\n/3JWbJVERFxMGgJpQUrTMerUCmY3C2lfPBm48ZmPCjmUUdWsh5vu2pVe+3hBIFeb\nY/kkOuRqAmiW+EmjFNQNdcxsDstd1AeipapPSH0TLWTqvAs8MndoNmfHyOFomV38\nEls5LL5Pomm27oVq6JM1geF1jKShAnO/w/dlRXcB0PFJIlpWKpw7OE5qqPpoiZY=\n-----END CERTIFICATE-----",
"PEMKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\n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\nBlK3Zix8WqtE14P/MNzfaA==\n-----END ENCRYPTED PRIVATE KEY-----",
"Password": "testPassword"
}
}
},
}
}

已经在为VKProxy写UI配置站点和文档了的更多相关文章

  1. Swagger UI教程 API 文档神器 搭配Node使用 web api 接口文档 (转)

    http://www.68idc.cn/help/makewebs/qitaasks/20160621620667.html 两种方案 一.Swagger 配置 web Api 接口文档美化 二.通过 ...

  2. 【Xamarin挖墙脚系列:代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧(转)】

    正愁如何选择构建项目中的视图呢,现在官方推荐画板 Storybord...但是好像 xib貌似更胜一筹.以前的老棒子总喜欢装吊,用代码写....用代码堆一个HTML页面不知道你们尝试过没有.等页面做出 ...

  3. 代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧

    近期接触了几个刚入门的iOS学习者,他们之中存在一个普遍和困惑和疑问.就是应该怎样制作UI界面.iOS应用是非常重视用户体验的,能够说绝大多数的应用成功与否与交互设计以及UI是否美丽易用有着非常大的关 ...

  4. [cocos2dx笔记012]一定简易的UI配置类

    使用cocostudio能够装载编辑好的UI,可是过于复杂.特别是在加截UI后,发现触屏事件有些问题. 假设直接使用程序写死载入UI又过于麻烦.花点时间,添加了一个基于ini的UI配置类,眼下仅仅实现 ...

  5. 关于代码手写UI,xib和StoryBoard

    代码手写UI 这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用.Geek们喜欢用代码构建UI,是因为代码是键盘敲出来的,这样可以做到不开IB,手不离开键盘就完成工作,可以专注于编码环境, ...

  6. 关于如何写UI及屏幕适配的一些技巧

    因为公司开启了一个新的iOS项目, 所以近期比较忙, 没有更新博客,今天打算总结一下关于UI布局及屏幕适配的一些实战技巧,尤其使用纯代码,会对提升效率及代码易于维护等方面有明显帮助,这里提到的没有使用 ...

  7. Apache配置站点根目录、用户目录及页面访问属性

    一.配置站点根目录及页面访问属性 DocumentRoot "/www/htdoc" <Directory "/www/htdoc"> Option ...

  8. EDIT Ini写Ini配置

    EDIT Ini写Ini配置  uses IniFiles; {$R *.dfm}   function IniFileName:string; begin    Result:=ExtractFil ...

  9. [Intel Edison开发板] 06、Edison开发在linux中烧写、配置、搭建开发环境

    1.前言 linux上烧写.配置.搭建Edison环境,千万不要用默认的setup tool for ubuntu!!! (即使,你用的就是ubuntu) 因为,其默认的工具会从一个坏链接下载配置文件 ...

  10. phpStudy配置站点 解决You don't have permission to access / on this server

    1.配置站点:打开phpStudy->其他选项菜单->站点域名管理 2.配置站点:打开phpStudy->其他选项菜单->打开hosts 3.在apache的配置文件vhost ...

随机推荐

  1. rabbitmq的基本使用

    使用MQ的三大作用:1.同步变异步2.流量削峰3.解耦降低服务间的耦合性要不要使用MQ,需不需要使用MQ依据项目的需要做选择. 使用场景: 例如:注册用户时候,发送激活邮件.监控应用中抛出的异常,邮件 ...

  2. C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)

    前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...

  3. [tldr]github仓库添加release

    作为一个开源项目开发者,并且把自己的代码仓库托管到了github上面,所以,可以在github上提供自己的程序的release 这通常是通过二进制可执行文件的方式提供 新建草稿 点击create a ...

  4. windows下测试TCP/UDP端口连通性

    一.简介 最近调试项目的时候有需要测试UDP连接,所以顺便研究了一下. MaQaQ:省流,不介意下载工具的话就直接拉到最后看Advanced Port Scanner. 二.TCP 1.telnet( ...

  5. boot3+JDK17+spring-cloud-gateway:4.0.0+spring-cloud:2022.0.0.0+Nacos2.2.1配置动态路由的网关

    项目依赖 配置 # Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html # Nacos认证信息 spring.cloud.nacos.config ...

  6. Python提取pdf文字信息

    目录 Python提取pdf文字信息 需求 代码 总结 Python提取pdf文字信息 需求 今天教务处导出来我们全年级的成绩,一看吓一跳,我们的名字怎么不在文件名里,只能一个个找吗.事情开始变得离谱 ...

  7. BUUCTF---达芬奇的密码

    题目 达芬奇隐藏在蒙娜丽莎中的数字列:1 233 3 2584 1346269 144 5 196418 21 1597 610 377 10946 89 514229 987 8 55 6765 2 ...

  8. windows 本地部署DeepSeek

    一:前言: 那么为什么要本地部署,主要就是企业或者个人为了数据安全和防止受限网络等其 数据安全:数据不用上传到外面,在本地处理,不用担心数据泄露,像金融.医疗这些对数据安全要求高的行业特别需要. 功能 ...

  9. Markdown 中如何添加图片

    语法 ![alt text](uri "optional title") alt text:可选,图片标签,用来描述的关键词,图片加载错误时候的替代文本,也可用于SEO. uri: ...

  10. 分享 3 款基于 .NET 开源且免费的远程桌面工具

    前言 今天大姚给大家分享 3 款基于 .NET 开源.免费.功能强大的远程桌面工具,希望可以给大家的远程工作和学习带来便利. 1Remote 1Remote是一款基于 .NET 开源(GPL-3.0 ...