Envoy IP 标签(IP Tagging)功能实现分析

1. 概述

Envoy 的 IP 标签(IP Tagging)功能是一个强大而灵活的流量分类工具,提供了基于源 IP 地址的标签匹配和头部添加功能。它通过使用高效的 LC-Trie 算法实现快速的 IP 地址匹配,并提供了详细的统计信息,帮助监控和识别流量模式。

它通过将源 IP 地址与预配置的 CIDR 范围进行匹配,为匹配成功的请求添加 x-envoy-ip-tags 头部,包含匹配到的标签。

通过使用 IP 标签功能,您可以:

  1. 为请求添加标签,便于日志记录和统计分析

  2. 与其他过滤器配合使用,提供更精细的访问控制

  3. 简化基于源 IP 地址的策略配置

  4. 支持运行时配置,可动态启用/禁用功能

  5. 提供详细的统计信息,帮助监控和识别流量模式

该功能在微服务架构中特别重要,可以帮助您管理多个服务的访问控制,确保只有授权的用户和服务能够访问受保护的资源,并为流量分析和监控提供有价值的信息。

2. 解决的问题

IP 标签功能主要解决以下问题:

2.1 流量分类与识别

  • 允许对流量进行基于源 IP 地址的分类

  • 为内部和外部流量提供不同的标签

  • 帮助识别来自特定区域或网络的请求

2.2 访问控制优化

  • 可以与其他过滤器(如 RBAC)配合使用,提供更精细的访问控制

  • 基于标签实现复杂的路由和限流策略

  • 简化基于源 IP 地址的策略配置

2.3 流量分析与监控

  • 为请求添加标签,便于日志记录和统计分析

  • 提供详细的统计信息,帮助监控和识别流量模式

  • 支持基于标签的指标收集和报警

2.4 性能优化

  • 使用 LC-Trie(最长前缀匹配)算法实现高效的 IP 地址匹配

  • 支持运行时配置,可动态启用/禁用功能

  • 与其他 Envoy 过滤器集成良好

3. 架构设计

3.1 核心组件架构

3.2 类图

3. 配置用例

3.1 基础配置

bash 复制代码
http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: BOTH    ip_tags:    - ip_tag_name: "internal"      ip_list:      - address_prefix: "10.0.0.0"        prefix_len: 8      - address_prefix: "172.16.0.0"        prefix_len: 12      - address_prefix: "192.168.0.0"        prefix_len: 16    - ip_tag_name: "test"      ip_list:      - address_prefix: "10.10.0.0"        prefix_len: 16    - ip_tag_name: "production"      ip_list:      - address_prefix: "52.100.0.0"        prefix_len: 16

3.2 运行时配置

javascript 复制代码
layered_runtime:  layers:  - name: static_layer    static_layer:      ip_tagging:        http_filter_enabled: true

3.3 高级配置

bash 复制代码
http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: EXTERNAL    ip_tags:    - ip_tag_name: "eu-west-1"      ip_list:      - address_prefix: "34.240.0.0"        prefix_len: 12      - address_prefix: "52.17.0.0"        prefix_len: 16    - ip_tag_name: "us-east-1"      ip_list:      - address_prefix: "3.208.0.0"        prefix_len: 12      - address_prefix: "52.95.0.0"        prefix_len: 16    - ip_tag_name: "ap-southeast-1"      ip_list:      - address_prefix: "13.250.0.0"        prefix_len: 12      - address_prefix: "18.139.0.0"        prefix_len: 16

3.4 与其他过滤器配合使用

bash 复制代码
http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: BOTH    ip_tags:    - ip_tag_name: "internal"      ip_list:      - address_prefix: "10.0.0.0"        prefix_len: 8    - ip_tag_name: "external"      ip_list:      - address_prefix: "0.0.0.0"        prefix_len: 0
- name: envoy.filters.http.rbac  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC    rules:      action: ALLOW      policies:        "internal_access":          permissions:          - or_rules:              rules:              - url_path_match:                  path: "/internal/*"          principals:          - request_header_match:              name: "x-envoy-ip-tags"              value: "internal"

4. 工作流程分析

4.1 过滤器执行流程

4.2 IP 标签匹配流程

5. 代码实现ER图

6. 最佳实践

6.1 标签设计原则

bash 复制代码
# 使用有意义的标签名称http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: BOTH    ip_tags:    - ip_tag_name: "eu-west-1"      ip_list:      - address_prefix: "34.240.0.0"        prefix_len: 12    - ip_tag_name: "us-east-1"      ip_list:      - address_prefix: "3.208.0.0"        prefix_len: 12    - ip_tag_name: "ap-southeast-1"      ip_list:      - address_prefix: "13.250.0.0"        prefix_len: 12

6.2 与其他过滤器配合使用

bash 复制代码
# 使用标签进行访问控制http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: BOTH    ip_tags:    - ip_tag_name: "internal"      ip_list:      - address_prefix: "10.0.0.0"        prefix_len: 8    - ip_tag_name: "external"      ip_list:      - address_prefix: "0.0.0.0"        prefix_len: 0
- name: envoy.filters.http.rbac  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC    rules:      action: ALLOW      policies:        "internal_access":          permissions:          - or_rules:              rules:              - url_path_match:                  path: "/internal/*"          principals:          - request_header_match:              name: "x-envoy-ip-tags"              value: "internal"

6.3 性能优化

bash 复制代码
# 使用最小权限原则http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: EXTERNAL    ip_tags:    - ip_tag_name: "trusted"      ip_list:      - address_prefix: "192.168.0.0"        prefix_len: 16      - address_prefix: "10.0.0.0"        prefix_len: 8    - ip_tag_name: "untrusted"      ip_list:      - address_prefix: "0.0.0.0"        prefix_len: 0

6.4 运行时配置

bash 复制代码
# 使用运行时配置动态启用/禁用功能http_filters:- name: envoy.filters.http.ip_tagging  typed_config:    "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging    request_type: BOTH    ip_tags:    - ip_tag_name: "internal"      ip_list:      - address_prefix: "10.0.0.0"        prefix_len: 8
layered_runtime:  layers:  - name: static_layer    static_layer:      ip_tagging:        http_filter_enabled: true

7. 代码实现细节

7.1 过滤器初始化

php 复制代码
IpTaggingFilterConfig::IpTaggingFilterConfig(    const envoy::extensions::filters::http::ip_tagging::v3::IPTagging& config,    const std::string& stat_prefix, Stats::Scope& scope, Runtime::Loader& runtime)    : request_type_(requestTypeEnum(config.request_type())), scope_(scope), runtime_(runtime),      stat_name_set_(scope.symbolTable().makeSet("IpTagging")),      stats_prefix_(stat_name_set_->add(stat_prefix + "ip_tagging")),      no_hit_(stat_name_set_->add("no_hit")), total_(stat_name_set_->add("total")),      unknown_tag_(stat_name_set_->add("unknown_tag.hit")) {
  // 检查是否配置了 IP 标签  if (config.ip_tags().empty()) {    throw EnvoyException("HTTP IP Tagging Filter requires ip_tags to be specified.");  }
  // 构建标签数据结构  std::vector<std::pair<std::string, std::vector<Network::Address::CidrRange>>> tag_data;  tag_data.reserve(config.ip_tags().size());
  for (const auto& ip_tag : config.ip_tags()) {    std::vector<Network::Address::CidrRange> cidr_set;    cidr_set.reserve(ip_tag.ip_list().size());
    for (const envoy::config::core::v3::CidrRange& entry : ip_tag.ip_list()) {      Network::Address::CidrRange cidr_entry = Network::Address::CidrRange::create(entry);      if (cidr_entry.isValid()) {        cidr_set.emplace_back(std::move(cidr_entry));      } else {        throw EnvoyException(            fmt::format("invalid ip/mask combo '{}/{}' (format is <ip>/<# mask bits>)",                        entry.address_prefix(), entry.prefix_len().value()));      }    }
    tag_data.emplace_back(ip_tag.ip_tag_name(), cidr_set);    stat_name_set_->rememberBuiltin(absl::StrCat(ip_tag.ip_tag_name(), ".hit"));  }
  // 创建 LC-Trie 用于快速 IP 地址匹配  trie_ = std::make_unique<Network::LcTrie::LcTrie<std::string>>(tag_data);}

7.2 标签匹配逻辑

php 复制代码
Http::FilterHeadersStatusIpTaggingFilter::decodeHeaders(Http::RequestHeaderMap& headers, bool) {  const bool is_internal_request = headers.EnvoyInternalRequest() &&                                   (headers.EnvoyInternalRequest()->value() ==                                    Http::Headers::get().EnvoyInternalRequestValues.True.c_str());
  // 检查是否应该应用过滤器  if ((is_internal_request && config_->requestType() == FilterRequestType::EXTERNAL) ||      (!is_internal_request && config_->requestType() == FilterRequestType::INTERNAL) ||      !config_->runtime().snapshot().featureEnabled("ip_tagging.http_filter_enabled", 100)) {    return Http::FilterHeadersStatus::Continue;  }
  // 匹配 IP 地址到标签  std::vector<std::string> tags =      config_->trie().getData(callbacks_->streamInfo().downstreamAddressProvider().remoteAddress());
  if (!tags.empty()) {    const std::string tags_join = absl::StrJoin(tags, ",");    headers.appendEnvoyIpTags(tags_join, ",");
    // 清除路由缓存,以便后续可以匹配到 x-envoy-ip-tags 头部    callbacks_->clearRouteCache();
    // 记录匹配到的标签统计    for (const std::string& tag : tags) {      config_->incHit(tag);    }  } else {    config_->incNoHit();  }
  config_->incTotal();  return Http::FilterHeadersStatus::Continue;}

7.3 统计信息更新

css 复制代码
void IpTaggingFilterConfig::incCounter(Stats::StatName name) {  Stats::SymbolTable::StoragePtr storage = scope_.symbolTable().join({stats_prefix_, name});  scope_.counterFromStatName(Stats::StatName(storage.get())).inc();}
void IpTaggingFilterConfig::incHit(absl::string_view tag) {  incCounter(stat_name_set_->getBuiltin(absl::StrCat(tag, ".hit"), unknown_tag_));}
void IpTaggingFilterConfig::incNoHit() {  incCounter(no_hit_);}
void IpTaggingFilterConfig::incTotal() {  incCounter(total_);}
相关推荐
楼兰公子2 小时前
《深入理解Linux网络技术内幕》全套学习资料合集
linux·网络·应用·驱动
想唱rap2 小时前
IO多路转接之epoll
linux·运维·服务器·数据库·网络协议·算法·http
Lust Dusk2 小时前
2026年最新phpstorm安装下载教程(附带激活链接)
网络·ide·安全·网络安全·phpstorm
福大大架构师每日一题2 小时前
ragflow v0.25.4 版本更新:RESTful API 数据源连接器、Agent 标签管理、Widget 持久化、GPT-5.4 模型支持全面升级
网络·gpt·restful
梓䈑2 小时前
【Linux网络】构建UDP网络服务:从Echo到聊天室的线程池架构演进
linux·网络·c++·udp
byte轻骑兵2 小时前
【LE Audio】CAP精讲[8]:CCID绑定术,打通音频流与控制的任督二脉
网络·人工智能·音视频·le audio·音视频控制
初願致夕霞2 小时前
Linux网络编程_数据链路层MAC帧协议与ARP协议
linux·网络·网络协议·macos
仍然.2 小时前
传输层协议TCP
服务器·网络协议·tcp/ip
十五年专注C++开发2 小时前
QHttp: 一个开源的轻量级、异步、高性能 HTTP 库
c++·qt·网络协议·http·qhttp