爱做网站yeele,洛阳网络推广,书签制作方法图片大全,网页游戏网页打不开在本文档中#xff0c;我们详细介绍了Kong Gateway的代理功能#xff0c;包括其路由能力和内部工作原理。
Kong Gateway提供了一些接口#xff0c;可以通过以下配置属性进行调整#xff1a;
proxy_listen#xff0c;定义了Kong Gateway将接受来自客户端的公共HTTP#…在本文档中我们详细介绍了Kong Gateway的代理功能包括其路由能力和内部工作原理。
Kong Gateway提供了一些接口可以通过以下配置属性进行调整
proxy_listen定义了Kong Gateway将接受来自客户端的公共HTTPgRPCWebSocket等流量并代理到upstream 服务的地址/端口列表默认为8000。 admin_listen同样定义了地址和端口列表但这些应该限制为仅由管理员访问因为它们暴露了Kong的配置能力Admin API默认为8001。 重要提示如果您需要在生产环境中将admin_listen端口暴露给Internet 请使用身份验证进行安全保护。 stream_listen类似于proxy_listen但用于层4TCP、TLS通用代理。默认情况下此功能已关闭。
术语Terminology
客户端Client指从下游发起请求到Kong Gateway的代理端口的客户端。上游服务Upstream service指您自己的API/服务位于Kong Gateway后面将客户端的请求/连接转发到此服务上。服务Service服务实体顾名思义是您自己的每个上游服务的抽象。服务的示例可能是数据转换微服务、计费API等。路由Route这指的是Kong Gateway的路由实体。路由是进入Kong Gateway的入口点定义请求匹配规则并将其路由到指定的服务。插件Plugin这是指Kong Gateway的“插件”它们是在代理生命周期中运行的业务逻辑组件。插件可以通过Admin API进行配置可以全局配置适用于所有传入流量也可以针对特定的路由和服务进行配置。
概览
从高层次的角度来看Kong Gateway在其配置的代理端口默认为8000和8443上监听HTTP流量并在显式配置的stream_listen端口上监听L4流量。Kong Gateway将根据您配置的路由对任何传入的HTTP请求或L4连接进行评估并尝试找到匹配的路由。如果给定的请求符合特定路由的规则Kong Gateway将处理请求的代理过程。 由于每个路由可能与一个服务相关联Kong Gateway将在您配置的路由及其关联的服务上运行已配置的插件然后将请求代理到上游。您可以通过Kong Gateway的Admin API管理路由。路由具有用于路由和匹配传入HTTP请求的特殊属性。不同子系统HTTP/HTTPS、gRPC/gRPCS和TCP/TLS的路由属性会有所不同。
子系统和路由属性
HTTP - 方法Methods - 主机Hosts - 头部Headers - 路径Paths如果是HTTPS还包括SNIs
TCP - 源地址Sources - 目标地址Destinations如果是TLS还包括SNIs
gRPC - 主机Hosts - 头部Headers - 路径Paths如果是gRPCS还包括SNIs
如果您尝试配置一个具有不支持的路由属性的路由例如使用源地址或目标地址字段的HTTP路由系统将报告一个错误消息
HTTP/1.1 400 Bad Request
Content-Type: application/json
Server: kong/x.x.x{code: 2,fields: {sources: cannot set sources when protocols is http or https},message: schema violation (sources: cannot set sources when protocols is http or https),name: schema violation
}如果Kong Gateway收到一个无法与任何配置的路由匹配的请求或者没有配置路由它将做出以下响应
HTTP/1.1 404 Not Found
Content-Type: application/json
Server: kong/x.x.x{message: no route and no Service found with those values
}如何配置一个服务
将服务添加到Kong Gateway中是通过向Admin API发送HTTP请求来完成的。
curl -i -X POST http://localhost:8001/services/ \-d namefoo-service \-d urlhttp://foo-service.com响应
HTTP/1.1 201 Created
...{connect_timeout: 60000,created_at: 1515537771,host: foo-service.com,id: d54da06c-d69f-4910-8896-915c63c270cd,name: foo-service,path: /,port: 80,protocol: http,read_timeout: 60000,retries: 5,updated_at: 1515537771,write_timeout: 60000
}这个请求指示Kong Gateway注册一个名为“foo-service”的服务该服务指向http://foo-service.com您的上游服务。
注意url参数是一个简写参数一次性填充协议protocol、主机host、端口port和路径path属性。
现在为了通过Kong Gateway发送流量到该服务我们需要指定一个路由它作为Kong Gateway的入口点
curl -i -X POST http://localhost:8001/routes/ \-d hosts[]example.com \-d paths[]/foo \-d service.idd54da06c-d69f-4910-8896-915c63c270cd响应
HTTP/1.1 201 Created
...{created_at: 1515539858,hosts: [example.com],id: ee794195-6783-4056-a5cc-a7e0fde88c81,methods: null,paths: [/foo],preserve_host: false,priority: 0,protocols: [http,https],service: {id: d54da06c-d69f-4910-8896-915c63c270cd},strip_path: true,updated_at: 1515539858
}我们现在已经配置了一个路由用于匹配与给定主机和路径相符的传入请求并将它们转发到我们配置的foo-service从而代理此流量到http://foo-service.com。
Kong Gateway是一个透明代理默认情况下将请求原封不动地转发到您的上游upstream 服务除了根据HTTP规范需要的Connection、Date和其他各种标头之外。
路由和匹配能力
现在让我们讨论一下Kong Gateway如何根据配置的路由属性来匹配请求。
Kong Gateway支持原生的HTTP/HTTPS、TCL/TLS和GRPC/GRPCS协议的代理正如之前提到的每个协议都接受不同的路由属性集合
HTTP方法methods、主机hosts、头部headers、路径paths如果是HTTPS还包括SNIsTCP源地址sources、目标地址destinations如果是TLS还包括SNIsgRPC主机hosts、头部headers、路径paths如果是GRPCS还包括SNIs
请注意所有这些字段都是可选的但至少必须指定其中一个。
对于请求匹配一个路由
- 请求必须包含所有配置的字段 - 请求中的字段值必须与至少一个配置的值匹配虽然字段配置接受一个或多个值但只需要请求中的一个值与配置值相匹配就被认为是匹配的
让我们通过几个示例来说明。考虑一个配置如下的路由
{hosts: [example.com, foo-service.com],paths: [/foo, /bar],methods: [GET]
}一些可能匹配此路由的请求示例如下
GET /foo HTTP/1.1
Host: example.com
GET /bar HTTP/1.1
Host: foo-service.comGET /foo/hello/world HTTP/1.1
Host: example.com这三个请求都满足路由定义中的所有条件。
然而以下请求将不符合配置的条件
GET / HTTP/1.1
Host: example.comPOST /foo HTTP/1.1
Host: example.comGET /foo HTTP/1.1
Host: foo.com这三个请求只满足了两个配置条件。第一个请求的路径与任何配置的路径都不匹配第二个请求的HTTP方法也是如此第三个请求的Host头部同样如此。
现在我们已经了解了路由属性如何一起工作让我们分别探讨每个属性。
请求头
Kong Gateway支持根据任意HTTP头部进行路由。其中的一个特例是通过Host头部进行路由。
基于请求的Host头部进行路由是通过Kong Gateway代理流量的最直接的方式特别是因为这也是HTTP Host头部的预期用法。Kong Gateway通过路由实体的hosts字段使此操作变得容易。
hosts字段接受多个值当通过Admin API指定时这些值必须使用逗号分隔并以JSON负载表示
curl -i -X POST http://localhost:8001/routes/ \-H Content-Type: application/json \-d {hosts:[example.com, foo-service.com]}响应
HTTP/1.1 201 Created
...由于Admin API也支持form-urlencoded内容类型您可以使用[]表示法指定一个数组
curl -i -X POST http://localhost:8001/routes/ \-d hosts[]example.com \-d hosts[]foo-service.com响应
HTTP/1.1 201 Created
...为了满足此路由的hosts条件任何来自客户端的传入请求现在必须将其Host头部设置为以下之一
Host: example.com或者
Host: foo-service.com类似地任何其他头部都可以用于路由
curl -i -X POST http://localhost:8001/routes/ \-d headers.regionnorth响应
HTTP/1.1 201 Created包含设置为North的Region头部的传入请求将被路由到该路由。
Region: North使用通配符主机名
为了提供灵活性Kong Gateway允许您在hosts字段中使用通配符来指定主机名。通配符主机名允许任何匹配的Host头部满足条件从而匹配给定的路由。
通配符主机名必须在域的最左边或最右边的标签中只包含一个星号。例如
*.example.com将允许a.example.com和x.y.example.com等Host值匹配。example.*将允许example.com和example.org等Host值匹配。
一个完整的示例如下所示
{hosts: [*.example.com, service.com]
}这将允许以下请求与此路由匹配
GET / HTTP/1.1
Host: an.example.comGET / HTTP/1.1
Host: service.compreserve_host属性
在代理时Kong Gateway的默认行为是将upstream请求的Host头部设置为服务的主机名。preserve_host字段接受一个布尔标志指示Kong Gateway不要这样做。
例如当preserve_host属性没有更改且路由配置如下时
{hosts: [service.com],service: {id: ...}
}客户端发送给Kong Gateway的可能请求示例如下
GET / HTTP/1.1
Host: service.comKong Gateway会从服务的host属性中提取Host头部的值并发送以下的上游请求
GET / HTTP/1.1
Host: my-service-host.com然而通过显式配置preserve_hosttrue的路由
{hosts: [service.com],preserve_host: true,service: {id: ...}
}假设来自客户端的相同请求
GET / HTTP/1.1
Host: service.comKong Gateway将保留客户端请求中的Host并发送以下的上游请求
GET / HTTP/1.1
Host: service.com额外的请求头部
可以通过除了Host以外的其他头部来路由请求。
要做到这一点请使用路由中的headers属性
{headers: { version: [v1, v2] },service: {id: ...}
}考虑到一个具有类似以下请求头部的请求
GET / HTTP/1.1
version: v1这个请求将被路由到该服务。同样的情况也适用于这个请求
GET / HTTP/1.1
version: v2但是这个请求没有被路由到该服务
GET / HTTP/1.1
version: v3注意headers的键使用逻辑与运算它们的值使用逻辑或运算。
请求路径
路由匹配的另一种方式是通过请求路径。为了满足这个路由条件客户端请求的标准化路径必须以paths属性的一个值开头。
例如使用如下配置的路由
{paths: [/service, /hello/world]
}以下请求将匹配此路由
GET /service HTTP/1.1
Host: example.comGET /service/resource?paramvalue HTTP/1.1
Host: example.comGET /hello/world/resource HTTP/1.1
Host: anything.com对于这些请求中的每一个Kong Gateway会检测到它们的标准化URL路径以routes的paths值之一作为前缀。默认情况下Kong Gateway将无需更改URL路径将请求代理到上游。
在使用路径前缀进行代理时最长的路径首先进行评估。这样可以确保您定义的两个路径为/service和/service/resource的路由不会相互遮挡。
在路径中使用正则表达式
对于要被视为正则表达式的路径必须以~作为前缀
paths: [~/foo/bar$]任何没有以~作为前缀的路径都将被视为纯文本
paths: [/users/\d/profile, /following]评估顺序
路由器使用路由配置中的regex_priority字段评估路由。更高的regex_priority值表示更高的优先级。
[{paths: [~/status/\d],regex_priority: 0},{paths: [~/version/\d/status/\d],regex_priority: 6},{paths: /version,},{paths: [~/version/any/],}
]在这种情况下Kong Gateway按照以下顺序评估传入的请求对定义的URI进行匹配
/version/\d/status/\d/status/\d/version/any//version
具有大量正则表达式的路由器可能会占用本应用于其他规则的流量。构建和执行正则表达式要耗费更多资源并且不容易优化。您可以使用路由器表达式语言来避免创建复杂的正则表达式。
如果您遇到意外的行为请使用Kong的调试头部来帮助追踪问题的来源
在kong.conf中将allow_debug_header设置为on。在您的请求头部中发送Kong-Debug: 1以便在响应头部中指示匹配的路由ID用于故障排除目的。
与往常一样一个请求仍然必须匹配路由的hosts和methods属性Kong Gateway会遍历您的路由直到找到匹配最多规则的路由。
捕获组
捕获组也被支持匹配的组将从路径中提取出来并可以供插件使用。如果我们考虑以下的正则表达式
/version/(?version\d)/users/(?user\S)以及以下请求路径
/version/1/users/johnKong Gateway认为请求路径匹配并且如果整个路由也匹配考虑其他路由属性提取的捕获组将在ngx.ctx变量中对插件可用
local router_matches ngx.ctx.router_matches-- router_matches.uri_captures is:
-- { 1, john, version 1, user john }转义特殊字符
接下来值得注意的是根据RFC 3986正则表达式中的字符通常被视为保留字符因此应进行百分比编码。当通过Admin API配置具有正则表达式路径的路由时如果有必要请确保对有效负载进行URL编码。例如使用curl并使用application/x-www-form-urlencoded MIME类型
curl -i -X POST http://localhost:8001/routes \--data-urlencode uris[]/status/\d响应
HTTP/1.1 201 Created
...请注意curl不会自动URL编码您的有效负载并且请注意使用--data-urlencode它防止字符被URL解码并被Kong Gateway的Admin API解释为空格 。
strip_path属性
为了在匹配路由时指定路径前缀但不在上游请求中包含该前缀可以使用strip_path布尔属性通过配置路由来实现
{paths: [/service],strip_path: true,service: {id: ...}
}启用此标志会告诉Kong Gateway在匹配此路由并代理至服务时不应在上游请求的URL中包含URL路径的匹配部分。例如对于上述路由的以下客户端请求
GET /service/path/to/resource HTTP/1.1
Host: ...这将导致Kong Gateway发送以下的上游请求
GET /path/to/resource HTTP/1.1
Host: ...同样地如果在已启用strip_path的路由上定义了一个正则表达式路径则会剥离请求URL匹配序列的全部内容。例如
{paths: [/version/\d/service],strip_path: true,service: {id: ...}
}匹配所提供的正则表达式路径的以下HTTP请求
GET /version/1/service/path/to/resource HTTP/1.1
Host: ...由Kong Gateway作为上游代理发送的请求为
GET /path/to/resource HTTP/1.1
Host: ...规范化行为
为了防止绕过常规路由匹配客户端发来的请求URI在路由匹配前根据RFC 3986进行规范化。具体而言对于传入的请求URI会使用以下规范化技术这些技术被选择是因为它们通常不改变请求URI的语义
1. 百分号编码的三元组将转换为大写。例如/foo%3a 转换为 /foo%3A。 2. 百分号编码的非保留字符将被解码。例如/fo%6F 解码为 /foo。 3. 必要时删除点段dot segments。例如/foo/./bar/../baz 删除为 /foo/baz。 4. 合并重复斜杠。例如/foo//bar 合并为 /foo/bar。
Route对象的paths属性也被规范化。首先确定路径是普通文本还是正则表达式路径然后使用不同的规范化技术。
对于普通文本路由路径
与上述相同的规范化技术被使用即方法1到4。
对于正则表达式路由路径
只使用方法1和2。此外如果解码后的字符成为正则表达式元字符将使用反斜杠进行转义。
Kong Gateway在执行路由匹配之前将规范化任何传入的请求URI。因此发送到上游服务的任何请求URI也将保持规范化形式以保留原始URI的语义。
请求的HTTP方法
methods字段允许根据请求的HTTP方法进行匹配。它可以接受多个值。默认值为空不使用HTTP方法进行路由。
以下路由允许通过GET和HEAD进行路由
{methods: [GET, HEAD],service: {id: ...}
}这样的路由将与以下请求匹配
GET / HTTP/1.1
Host: ...HEAD /resource HTTP/1.1
Host: ...但它不会与POST或DELETE请求匹配。这在配置路由上允许更精确的细粒度控制。例如可以想象有两个指向相同服务的路由一个允许无限制的非身份验证GET请求另一个只允许通过身份验证和速率限制的POST请求通过将身份验证和速率限制插件应用于这些请求。
请求来源
注意此部分仅适用于TCP和TLS路由。
sources路由属性允许通过一组传入连接的IP和/或端口源来匹配路由。
以下路由允许通过一组源IP/端口进行路由
{protocols: [tcp, tls],sources: [{ip:10.1.0.0/16, port:1234}, {ip:10.2.2.2}, {port:9123}],id: ...,
}来自CIDR范围为“10.1.0.0/16”或IP地址为“10.2.2.2”或端口为“9123”的TCP或TLS连接将匹配此路由。
请求目标
注意本部分仅适用于TCP和TLS路由。
类似于sources属性destinations属性允许通过传入连接的IP和/或端口的列表来匹配路由但使用TCP/TLS连接的目标作为路由属性。
请求 SNI
当使用安全协议如https、grpcs或tls时可以使用服务器名称指示作为路由属性。以下路由允许通过SNIs进行路由选择
{snis: [foo.test, example.com],id: ...
}与TLS连接的SNI扩展中设置的匹配主机名的传入请求将被路由到此路由。如前所述SNI路由不仅适用于TLS还适用于通过TLS传输的其他协议例如HTTPS等。如果在路由中指定了多个SNI则其中任何一个都可以与传入请求的SNI匹配名称之间使用OR关系。
SNI在TLS握手时指示并且在建立TLS连接后无法修改。这意味着例如多个重复使用相同keepalive连接的请求在执行路由匹配时将具有相同的SNI主机名而不考虑Host头信息。
也就是说在执行路由匹配时通过保持活动连接发送多个请求的情况下这些请求将具有相同的SNI主机名不考虑Host头信息。
请注意可以创建具有不匹配的SNI和Host头信息匹配器的路由但通常不建议这样做。
匹配优先级
一条路由可以根据其头信息headers、主机名hosts、路径paths和方法methods定义匹配规则对于安全路由还包括SNIs字段https、grpcs、tls。为了使Kong Gateway能将传入请求与路由匹配必须满足所有字段的条件。然而Kong Gateway允许一定的灵活性允许配置两个或多个具有相同值的字段的路由 - 当发生这种情况时Kong Gateway应用优先级规则。
规则是在评估请求时Kong Gateway首先尝试匹配具有最多规则的路由。
例如如果配置了两个路由如下
{hosts: [example.com],service: {id: ...}
},
{hosts: [example.com],methods: [POST],service: {id: ...}
}第二个路由有hosts字段和methods字段所以Kong Gateway首先对其进行评估。通过这样做我们避免了第一个路由“掩盖”了本应为第二个路由而来的请求。
因此这个请求匹配了第一个路由
GET / HTTP/1.1
Host: example.com而这个请求匹配了第二个路由
POST / HTTP/1.1
Host: example.com按照这个逻辑如果配置了第三个路由该路由具有hosts字段、methods字段和uris字段它将首先由Kong Gateway进行评估。
如果两个路由A和B在给定请求中的规则数量相同则将按照以下列出的顺序应用下面的决胜规则。如果符合以下条件之一将选择路由A而不是B
- 路由A只有普通主机头(headers)而路由B有一个或多个通配符主机头 - 路由A具有比路由B更多的非主机头(headers) - 路由A至少有一个正则表达式路径(paths)而路由B只有普通路径 - A中最长的路径比B中最长的路径更长 - A.created_at B.created_at (创建时间早于B)
代理行为
上述的代理规则详细说明了Kong Gateway如何将传入的请求转发给上游服务。下面我们将详细介绍Kong Gateway在匹配HTTP请求与注册路由之间以及实际转发请求之间发生的内部过程。
负载均衡
Kong Gateway实现了负载均衡功能以将被代理的请求分配到上游服务的一组实例之间。
插件执行
Kong Gateway通过插件进行扩展这些插件将自身挂接在被代理请求的请求/响应生命周期中。插件可以在您的环境中执行各种操作并对被代理请求进行转换。
插件可以配置为全局运行对所有被代理流量或在特定路由和服务上运行。在这两种情况下您都必须通过Admin API创建插件配置。
一旦匹配了路由以及其关联的服务实体Kong Gateway将运行与这些实体相关联的插件。在路由上配置的插件会在服务上配置的插件之前运行但除此之外插件关联的常规规则仍适用。
这些配置的插件将运行它们的访问阶段您可以在插件开发指南中找到有关此阶段的更多信息。
代理和上游upstream 超时
一旦Kong Gateway执行了所有必要的逻辑包括插件它就准备将请求转发给上游服务。这是通过Nginx的ngx_http_proxy_module来实现的。您可以通过以下服务属性来配置Kong Gateway与特定上游之间的连接超时时间
connect_timeout定义与上游服务建立连接的超时时间以毫秒为单位。默认为60000毫秒。write_timeout定义传输请求到上游服务的两次连续写操作之间的超时时间以毫秒为单位。默认为60000毫秒。read_timeout定义接收来自上游服务的请求的两次连续读取操作之间的超时时间以毫秒为单位。默认为60000毫秒。
Kong Gateway将使用HTTP/1.1发送请求并设置以下头部信息
Host: your_upstream_host如文档中先前描述的那样。Connection: keep-alive以允许复用上游连接。X-Real-IP: remote_addr其中$remote_addr是ngx_http_core_module提供的同名变量。请注意$remote_addr可能被ngx_http_realip_module覆盖。X-Forwarded-For: address其中address是由ngx_http_realip_module提供的$realip_remote_addr的内容附加到具有相同名称的请求头中。X-Forwarded-Proto: protocol其中protocol是客户端使用的协议。如果$realip_remote_addr是受信任的地址之一则转发具有相同名称的请求头如果提供。否则将使用ngx_http_core_module提供的$scheme变量的值。X-Forwarded-Host: host其中host是客户端发送的主机名。如果$realip_remote_addr是受信任的地址之一则转发具有相同名称的请求头如果提供。否则将使用ngx_http_core_module提供的$host变量的值。X-Forwarded-Port: port其中port是接受请求的服务器的端口。如果$realip_remote_addr是受信任的地址之一则转发具有相同名称的请求头如果提供。否则将使用ngx_http_core_module提供的$server_port变量的值。X-Forwarded-Prefix: path其中path是由Kong Gateway接受的请求的路径。如果$realip_remote_addr是受信任的地址之一则转发具有相同名称的请求头如果提供。否则将使用ngx_http_core_module提供的$request_uri变量的值去除查询字符串。 注意Kong Gateway将对空路径返回“/”但不会对请求路径进行其他规范化处理。
Kong Gateway会将所有其他请求头按原样转发。
唯一的例外是在使用WebSocket协议时。如果是这样Kong Gateway将设置以下头部以允许在客户端和上游服务之间升级协议
Connection: UpgradeUpgrade: websocket
错误和重试
每当在代理过程中发生错误时Kong Gateway会使用底层的Nginx重试机制将请求传递给下一个上游服务。
这里有两个可配置的元素
重试次数可以针对每个服务使用retries属性进行配置。有关详细信息请参阅管理API。什么样的情况被视为错误这里Kong Gateway使用的是Nginx的默认设置这意味着在与服务器建立连接、发送请求或读取响应头时发生错误或超时。
第二个选项是基于Nginx的proxy_next_upstream指令。这个选项不能直接通过Kong Gateway进行配置但可以通过自定义Nginx配置进行添加。
响应
Kong Gateway从上游服务接收响应并以流式传输的方式将其发送回下游客户端。此时Kong Gateway执行添加到路由和/或服务中的后续插件在header_filter阶段实现钩子功能。
一旦所有注册的插件的header_filter阶段被执行完毕Kong Gateway会添加以下头部并将完整的头部集合发送给客户端
Via: kong/x.x.x其中x.x.x是所使用的Kong Gateway版本号。X-Kong-Proxy-Latency: latency其中latency是Kong Gateway从客户端接收请求到将请求发送给上游服务所经过的时间以毫秒为单位。X-Kong-Upstream-Latency: latency其中latency是Kong Gateway等待上游服务响应的第一个字节所经过的时间以毫秒为单位。
一旦头部被发送给客户端Kong Gateway开始执行为路由和/或服务注册的插件这些插件实现了body_filter钩子。由于Nginx的流式传输特性该钩子可能会被调用多次。每个成功通过body_filter钩子处理的上游响应块都会被发送回客户端。您可以在插件开发指南中找到有关body_filter钩子的更多信息。
配置回退路由
作为Kong Gateway代理能力提供的灵活性的实际用例和示例让我们尝试实现一个回退路由以便在避免Kong Gateway响应HTTP 404 找不到路由的情况下可以捕获此类请求并将它们代理到特殊的上游服务或者对其应用插件例如此类插件可以使用不同的状态码终止请求或在不代理请求的情况下响应。
下面是一个这样的回退路由示例
{paths: [/],service: {id: ...}
}正如您所猜测的由于所有URI都以根字符/为前缀所以所有发送到Kong Gateway的HTTP请求实际上都会匹配此路由。正如我们从请求路径部分了解到的Kong Gateway优先评估最长的URL路径因此/路径将最后被Kong Gateway评估并有效提供一个回退路由只作为最后的备选方案进行匹配。然后您可以将流量发送到特殊服务或在该路由上应用任何您希望的插件。
为路由配置TLS
Kong Gateway提供了一种按连接动态提供TLS证书的方式。TLS证书由核心直接处理并通过Admin API进行配置。连接到Kong Gateway的TLS客户端必须支持服务器名称指示扩展以使用此功能。
TLS证书在Kong Gateway Admin API中由两个资源处理
/certificates用于存储您的密钥和证书。/snis将注册的证书与服务器名称指示关联起来。
以下是如何在给定路由上配置TLS证书的步骤首先通过Admin API上传您的TLS证书和密钥
curl -i -X POST http://localhost:8001/certificates \-F cert/path/to/cert.pem \-F key/path/to/cert.key \-F snis*.tls-example.com,other-tls-example.com响应
HTTP/1.1 201 Created
...snis表单参数是一个简化参数直接插入一个SNI并将上传的证书与其关联。
请注意snis中定义的一个SNI名称包含一个通配符*.tls-example.com。在最左边前缀或最右边后缀位置SNI可以包含一个单个通配符。当维护多个子域时这可能很有用。配置了一个带有通配符名称的单个sni可以用来匹配多个子域而不需要为每个子域创建一个SNI。
有效的通配符位置是mydomain.*、*.mydomain.com和*.www.mydomain.com。
可以使用以下参数在Kong Gateway配置中添加默认证书
ssl_certssl_cert_key
或者通过动态配置具有*的SNI的默认证书
curl -i -X POST http://localhost:8001/certificates \-F cert/path/to/default-cert.pem \-F key/path/to/default-cert.key \-F snis*响应
HTTP/1.1 201 Created
...snis的匹配遵循以下优先级
精确的SNI匹配证书按前缀通配符搜索证书按后缀通配符搜索证书搜索与SNI * 关联的证书文件系统上的默认证书
您现在必须在Kong Gateway中注册以下路由。为了方便起见我们只使用Host标头来匹配对该路由的请求
curl -i -X POST http://localhost:8001/routes \-d hostsprefix.tls-example.com,other-tls-example.com \-d service.idd54da06c-d69f-4910-8896-915c63c270cd响应
HTTP/1.1 201 Created
...您现在可以期望该路由通过Kong Gateway以HTTPS方式提供服务
curl -i https://localhost:8443/ \-H Host: prefix.tls-example.com响应
HTTP/1.1 200 OK
...在建立连接和进行TLS握手时如果您的客户端在SNI扩展中发送prefix.tls-example.comKong Gateway将提供先前配置的cert.pem证书。无论是HTTPS还是TLS连接都是如此。
限制客户端协议
路由具有protocols属性用于限制应该监听的客户端协议。该属性接受一组值可以是 http、https、grpc、grpcs、tcp 或 tls。
具有 http 和 https 的路由将接受两种协议的流量。
{hosts: [...],paths: [...],methods: [...],protocols: [http, https],service: {id: ...}
}不指定任何协议具有相同的效果因为路由默认为 [http, https]。
但是只有 https 的路由将仅接受通过HTTPS的流量。如果之前发生了来自受信任IP的TLS终止则它也将接受未加密的流量。当请求来自于trusted_ips中配置的IP之一并且设置了X-Forwarded-Proto: https头时认为TLS终止是有效的。
{hosts: [...],paths: [...],methods: [...],protocols: [https],service: {id: ...}
}如果上述那样的一个路由匹配了一个请求但该请求是明文传输且没有通过有效的TLS终止Kong Gateway会回复以下内容
HTTP/1.1 426 Upgrade Required
Content-Type: application/json; charsetutf-8
Transfer-Encoding: chunked
Connection: Upgrade
Upgrade: TLS/1.2, HTTP/1.1
Server: kong/x.y.z{message:Please use HTTPS protocol}可以通过在protocols属性中使用tcp来创建针对原始TCP不一定是HTTP连接的路由
{hosts: [...],paths: [...],methods: [...],protocols: [tcp],service: {id: ...}
}类似地我们可以使用tls值创建接受原始TLS流量不一定是HTTPS的路由
{hosts: [...],paths: [...],methods: [...],protocols: [tls],service: {id: ...}
}只有 TLS 的路由将仅接受 TLS 流量。
还可以同时接受 TCP 和 TLS 流量
{hosts: [...],paths: [...],methods: [...],protocols: [tcp, tls],service: {id: ...}
} 要使L4 TLS代理正常工作需要创建一个接受tls协议的路由并上传适当的TLS证书并将其sni属性正确设置为匹配传入连接的SNI。请参考上面的“为路由配置TLS”部分中的说明来进行设置。
代理WebSocket流量
Kong Gateway通过底层的Nginx实现来支持WebSocket流量。当您想要通过Kong Gateway在客户端和上游服务之间建立WebSocket连接时必须进行WebSocket握手。这是通过HTTP升级机制完成的。以下是您的客户端对Kong Gateway发出的请求的示例
GET / HTTP/1.1
Connection: Upgrade
Host: my-websocket-api.com
Upgrade: WebSocket这使得Kong Gateway将连接(Connection)和升级(Upgrade)头部转发给您的上游服务而不是由于标准HTTP代理的逐跳特性而将其丢弃。
WebSocket代理模式
Kong Gateway上有两种代理WebSocket流量的方法
1. HTTP(S)方式的服务和路由 2. WS(S)方式的服务和路由
HTTP(S)服务和路由
使用http和https协议的服务和路由完全能够处理WebSocket连接无需特殊配置。使用此方法WebSocket会话的行为与常规的HTTP请求完全相同所有的请求/响应数据都被视为一个不透明的字节流。
services:- name: my-http-websocket-serviceprotocol: httphost: 1.2.3.4port: 80path: /routes:- name: my-http-websocket-routeprotocols:- http- httpsWS(S)服务和路由企业版
除了HTTP服务和路由之外Kong Gateway Enterprise 还包括wsWebSocket-over-http和wssWebSocket-over-https选项作为服务协议和路由协议。与http/https不同ws和wss服务可以完全控制底层的WebSocket连接。这意味着它们可以使用WebSocket插件和WebSocket PDK来执行基于每个消息的业务逻辑消息验证、计费、速率限制等。
services:- name: my-dedicated-websocket-serviceprotocol: wshost: 1.2.3.4port: 80path: /routes:- name: my-dedicated-websocket-routeprotocols:- ws- wss注意与http(s)服务的协议无关行为相比解码和编码WebSocket消息会增加一定的性能开销。如果您的API不需要ws(s)服务提供的额外功能建议您改用http(s)服务。
WebSocket 和 TLS
不论使用哪种服务/路由协议http(s)或ws(s)Kong Gateway都将在相应的http和https端口上接受普通和TLS的WebSocket连接。要强制客户端使用TLS连接请将路由的protocols属性设置为仅限https或wss。
在设置服务以指向上游WebSocket服务时您应该仔细选择Kong Gateway与上游之间要使用的协议。
如果您想使用TLS您的上游WebSocket服务必须在服务协议属性中使用https或wss协议并使用正确的端口通常为443。如果想不使用TLS连接则应使用http或ws协议和端口通常为80。
如果您希望Kong Gateway终止TLS连接可以仅接受来自客户端的https/wss连接并在明文http或ws上代理到上游服务。
代理gRPC流量
Kong Gateway原生支持gRPC代理。为了管理gRPC服务并通过Kong Gateway代理gRPC请求需要为gRPC服务创建服务和路由。
目前仅支持与gRPC一起使用的可观测性和日志记录插件。在Kong Hub页面上可以在支持的协议字段中找到“grpc”和“grpcs”例如File Log插件的页面。
代理TCP/TLS流量
Kong Gateway原生支持TCP和TLS代理。
在这种模式下达到stream_listen端点的传入连接的数据将被传递到上游。还可以使用此模式终止来自客户端的TLS连接。
要使用此模式除了定义stream_listen之外还需要创建带有协议类型为tcp或tls的适当路由/服务对象。
如果希望Kong Gateway终止TLS连接则必须满足以下条件
Kong Gateway上用于TLS连接的端口必须启用ssl标志Kong Gateway内部必须存在可用于TLS终止的证书/密钥如在为路由配置TLS中所示。
Kong Gateway将使用连接客户端的TLS SNI服务器名称扩展来找到适用的TLS证书。
在服务端取决于Kong Gateway和上游服务之间的连接是否需要加密可以相应地设置tcp或tls协议类型。这意味着在这种模式下支持以下所有设置
客户端 - TLS - Kong - TLS - 上游客户端 - TLS - Kong - 明文 - 上游客户端 - 明文 - Kong - TLS - 上游
代理TLS透传流量
Kong Gateway支持代理TLS请求而无需终止或称为SNI代理。
Kong Gateway使用连接客户端的TLS SNI扩展来查找匹配的路由和服务并将完整的TLS请求转发到上游而不解密传入的TLS流量。
在这种模式下您需要执行以下操作
创建一个使用协议tls_passthrough的路由对象并将snis字段设置为一个或多个SNIs。将相应的服务对象的协议设置为tcp。将请求发送到具有流监听指令中ssl标志的端口。
不需要单独的SNI和证书实体也不会使用它们。
路由不允许同时匹配tls和tls_passthrough协议。然而相同的SNI可以在不同的路由中同时匹配tls和tls_passthrough协议。
还可以将路由设置为tls_passthrough服务设置为tls。在这种模式下与上游的连接将进行两次TLS加密。 注意要在此模式下运行任何插件插件的protocols字段必须包括tls_passthrough。