kube-proxy源码阅读(iptables实现)

2023-05-16

Reference

文章目录

  • 1 入口
  • 2 ProxyServer创建及调用
  • 3 ProxyServer 核心调用流程
    • 3.1 func (o *Options) Run() err
    • 3.2 func (o *Options) runLoop() error
    • 3.3 func (s *ProxyServer) Run() error
    • 3.4 func (proxier *Proxier) SyncLoop()
  • 4 资源事件处理流程
    • 4.1 Service事件
    • 4.2 Endpoints事件
    • 4.3 Nodes事件
    • 4.4 func (proxier *Proxier) Sync()
  • 5 代理规则同步处理流程
  • 6 数据包路径及链位置
    • 6.1 PREROUTING
      • 6.1.1 PREROUTING ->KUBE-SERVICES
      • 6.1.2 KUBE-SERVICES
        • 6.1.2.1 ClusterIP
          • 6.1.2.1.1 KUBE-SERVICES->KUBE-MARK-MASQ
          • 6.1.2.1.2 KUBE-SERVICES->KUBE-SVC-HASH
        • 6.1.2.2 External IP
          • 6.1.2.2.1 KUBE-SERVICES->KUBE-MARK-MASQ
          • 6.1.2.2.2 KUBE-SERVICES->KUBE-SVC-HASH
        • 6.1.2.3 LB IP
          • 6.1.2.3.1 KUBE-SERVICES->KUBE-FW-HASH
          • 6.1.2.3.2 KUBE-FW-HASH->KUBE-MARK-MASQ
          • 6.1.2.3.3 KUBE-FW-HASH->KUBE-SVC-HASH
          • 6.1.2.3.4 KUBE-FW-HASH->KUBE-MARK-DROP
        • 6.1.2.4 NodePort
          • 6.1.2.4.1 KUBE-SERVICES->KUBE-NODEPORTS
          • 6.1.2.4.2 KUBE-NODEPORTS->KUBE-MARK-MASQ
          • 6.1.2.4.3 KUBE-NODEPORTS->KUBE-SVC-HASH
        • 6.1.2.5 KUBE-SVC-HASH -> KUBE-SEP-HASH
        • 6.1.2.6 KUBE-SEP-HASH
    • 6.2 INPUT
      • 6.2.1 FILTER INPUT ->KUBE-SERVICES
      • 6.2.2 FILTER INPUT ->KUBE-EXTERNAL-SERVICES
    • 6.3 FORWARD
      • 6.3.1 FORWARD-> KUBE-FORWARD
      • 6.3.2 FORWARD-> KUBE-SERVICES
    • 6.4 OUTPUT
      • 6.4.1 NAT OUTPUT-> KUBE-SERVICES
      • 6.4.2 NAT OUTPUT-> KUBE-SERVICES
    • 6.5 POSTROUTING
      • 6.5.1 NAT POSTROUTING -> KUBE-POSTROUTING
  • 7 总结

1 入口

cmd目录下的proxy.go

 利用Cobra构建CLI接口,并对proxy server进行调用。

kubernetes/cmd/kube-proxy/proxy.go

func main() {
	rand.Seed(time.Now().UnixNano())
    
    // 核心调用
	command := app.NewProxyCommand()

	// TODO: once we switch everything over to Cobra commands, we can go back to calling
	// utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the
	// normalize func and add the go flag set by hand.
	pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
	pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
	// utilflag.InitFlags()
	logs.InitLogs()
	defer logs.FlushLogs()

	if err := command.Execute(); err != nil {
		os.Exit(1)
	}
}

2 ProxyServer创建及调用

kubernetes/cmd/kube-proxy/app/server.go

func NewProxyCommand() *cobra.Command {
    .....
    cmd := &cobra.Command{
        ......
        Run:func(cmd *cobra.Command, args []string) {
            ......
            opts.Run()
        }
    }
    .....
    opts.config, err = opts.ApplyDefaults(opts.config)
    .....
}

ApplyDefaults中会配置默认的参数。/pkg/proxy/apis中的init方法内,会向SchemeBuilder注册添加默认参数的方法。这里面对于Porxy会注册SetObjectDefaults_KubeProxyConfiguration,最后调用了SetDefaults_KubeProxyConfiguration其中IPTables.SyncPeriod.Duration,默认值为30S(该值为失败后的尝试retry间隔,可以使用–iptables-sync-period配置,其指定了iptables重刷新的最大间隔)

kubernetes/cmd/kube-proxy/app/server.go

func (o *Options) Run() error {
	defer close(o.errCh)
	if len(o.WriteConfigTo) > 0 {
		return o.writeConfigFile()
	}

	proxyServer, err := NewProxyServer(o)
	if err != nil {
		return err
	}

	if o.CleanupAndExit {
		return proxyServer.CleanupAndExit()
	}

	o.proxyServer = proxyServer
	return o.runLoop()
}
注意:这里BounedFrequencyRunner的同步方法为proxier.syncProxyRules,最小时间间隔为minSyncPeriod(可以使用参数--iptables-min-sync-period配置,未配置时,应该就是0),最大时间间隔为1小时,突发数为2,失败重试间隔为proxier.syncPeriod(默认为30秒,可以用参数--iptables-sync-period配置,其指定了iptables重刷新的最大间隔,不允许为0)

3 ProxyServer 核心调用流程

opts.Run()->

o.runLoop()->

o.proxyServer.Run()->

s.Proxier.SyncLoop()

3.1 func (o *Options) Run() err

在构建ProxyCommand时,会在其Run方法内调用该方法

  • (1)如kube-proxy命令调用时,传入了–write-config-to参数,则会将kube-proxy的默认配置打印到指定文件,然后退出。
  • (2)调用NewProxyServer方法,构建proxyServer
  • (3)如果kube-proxy命令调用时传入了–cleanup参数,则会清理iptables及ipvs配置,然后退出
  • (4)调用o.runLoop方法。

3.2 func (o *Options) runLoop() error

  • (1)如果o.Watcher(用于监听ConfigFile的更新变化)不为空,则调用o.watcher.Run()(这里如果监听到配置文件的写或者rename事件,会导致kube-proxy的退出)
  • (2)调用o.proxyServer.Run()

3.3 func (s *ProxyServer) Run() error

  • (1)如果启动参数中配置了–oom-score-adj(oom打分调整,OOM killer 会给进程打分,把 oom_score 最大的进程先杀死,如果这个值设置成负数,则表明不优先级杀死它,如果位正数则优先杀死,如果设置为0表明与用户不调整)。则为kube-proxy配置该值
  • (2)如果Broadcaster及EventClient不为空,则开启事件记录服务
  • (3)如果健康检查服务不会空,则启动
  • (4)如果指标绑定地址大于0,则启动服务
    • 1)curl 10.19.188.3:10249/proxyMode, 可以获得proxyMode运行模式
    • 2)curl curl 10.19.188.3:10249/metrics, 可以获得运行指标信息
  • (5)如过contracker会为空,则根据启动参数,配置系统contracker配置。(这里我们会把所有的contracker相关配置设置为0, 即不修改系统原先的conntrack配置)
    • 1)首先调用getConntrackMax,如果–conntrack-max-per-core参数不为空,且值大于0(不配置时,默认值为32768),则用其乘以cpu数,获取上限值,如果该值大于配置中的–conntrack-min,则返回该值,否则返回–conntrack-min。否则返回0
    • 2)如果max值大于0,则更新系统配置
    • 3)如果配置了–conntrack-tcp-timeout-close-wait duration,且其值大于0, 则更新系统值
    • 4)如果配置了–conntrack-tcp-timeout-established,且其值大于0,则更新系统中的该值。
  • (6)构建kube-proxy监听的server的选择器,及Informer(对于具有service.kubernetes.io/service-proxy-name及service.kubernetes.io/headless label的service不处理),注册service事件处理器,并启动
  • (7)如果使用EndpointSlices,则构建endpointsSlice事件处理器,并启动。否则构建endpoints事件处理器,并启动。
  • (8)启动informer
  • (9)如果使用了ServiceTopology门特性,则增加nodeInformer,及相关事件处理器,并启动
  • (10)记录启动事件
  • (11)调用s.Proxier.SyncLoop

3.4 func (proxier *Proxier) SyncLoop()

  • (1)如果proxier的健康检查服务不为空,则调用其update函数
  • (2)调用proxier.syncRunner.Loop(wait.NeverStop)

4 资源事件处理流程

在NewProxier时,会为其构建syncRunner,其绑定的处理函数为syncProxyRules。同时,调用ipt.Monitor(Monitor通过创建canary chain和轮询来检测给定的iptables表是否已被外部工具(例如,重新加载防火墙)刷新。 (具体来说,它每隔一段时间轮询[0]表,直到canary chain从表中删除,然后再等待一段额外的时间,以便从其余的表中也删除canary chain。 您可以通过在表[0]中列出一个相对空的表来优化轮询。 当检测到刷新时,将调用reloadFunc,以便调用者可以重新加载自己的iptables规则。 如果它无法创建检测链(无论是最初还是重新加载后),它将记录一个错误并停止监视。 (这个函数应该从goroutine中调用。))

4.1 Service事件

service Add\Update\Delete事件,会记录service变化,加入到proxier的serviceChanges中,并会调用proxier.Sync()方法

4.2 Endpoints事件

Endpoints Add\Update\Delete事件,会记录endpoints变化,加入到proxier的endpointsChanges中,会调用proxier.Sync()方法

4.3 Nodes事件

Nodes的Add\Update\Delete事件, 会调用proxier.syncProxyRules()

4.4 func (proxier *Proxier) Sync()

  • (1)如果proxier.healthzServer 不为空,则调用QueuedUpdate方法。会存储,事件时间。
  • (2)调用proxier.syncRunner.Run(),该方法会导致尝试调用syncProxyRules

5 代理规则同步处理流程

service/endpoints/node事件,最后都会导致syncProxyRules函数的调用

  • (1)如果proxier还没有初始化,则直接打印日志信息,返回.即只有在informer收到services和endpoints以后,才会进行真正的配置同步。
  • (2)构建defer func,记录其观察到的指标信息
  • (3)调用UpdateServiceMap,基于给定的ServiceChangeTracker,返回更新结果UpdateServiceMapResult,其包含了HCServiceNodePorts(HCServiceNodePorts是服务名称到节点端口号的映射,该映射指示该节点上该服务的健康状况)和UDPStaleClusterIP(持有UDP端口的过期的(不再分配给服务)Service IPs.调用者可以使用此信息中止超时等待或清除连接跟踪信息。)
    • 1)构建空Set集合赋值给UDPStaleClusterIP
    • 2)将ServiceChangeTracker中每个change的Current ServiceMap merge到proxier.ServiceMap中。用Curent ServiceMap 过滤change的Previous ServiceMap(即change的Previous ServiceMap中移除svcPortName中还在Curent中的项,剩下的就是无效的port),从proxier.ServiceMap中unmerge这些变化,同时将这些port中协议类型为TCP的ClusterIP加入到UDPStaleClusterIP集合中(svcPortName对象由ns,servicePort.Name,servicePort.Protocol组成。只有LB类型和NoePort类型Service才有可能会有HealthCheckNodePort–我们没有使用到这个字段)
    • 构建空HCServiceNodePorts集合
    • 遍历Merge以后的ServiceMap,如果其健康检查端口不为空,则将其加入到HCServiceNodePorts中。
  • (4)调用endpointsMap,基于endpoints变化,更新proxy.EndpointsMap,返回UpdateEndpointMapResult(包含HCEndpointsLocalIPSize–与kube-proxy同节点的endpoints的集合,StaleEndpoints–过期的endpoint service对,StaleServiceNames过期的service名字集合,LastChangeTriggerTimes所有endpoints变化的触发时间)
    • 1)构建空StaleEndpoints、StaleServiceNames、LastChangeTriggerTimes map
    • 2)调用apply方法,更新EndpointsMap,并用staleEndpoints存储不新鲜的 udp endpoints,用staleServiceNames 用于存储不新鲜的udp service .
    • 3)基于合并后的endpointsMap,获取本地的endpoints,填充HCEndpointsLocalIPSize。
  • (5)将endpointUpdateResult中的StaleServiceNames和serviceUpdateResult中的UDPStaleClusterIP进行合并,存入到staleServices中(里面记录了clusterIP以及ExternalIP)
  • (6)遍历iptablesJumpChains(kube-proxy在iptables原有链上,新建的Jump链)。确保每条目标Jump链,在表上存在(尝试去创建,如果创建失败,则根据返回值判断是否已经存在,如果创建失败,直接return).确保在源链上插入Jump规则,即kube-chanin(首先判断规则是否存在,如果不存在,则插入,这里应该是插入到表头位置)
  • (7)构建existingFilterChains map,清理proxier的existingFilterChainsData。
  • (8)调用SaveInto方法,将Filter表内的信息写入到proxier的existingFilterChainsData。(底层调用的命令:iptables-save -t filter)
# iptables-save -t filter 查询得到的结果中间省略了部分
*filter
:INPUT ACCEPT [272947:113632328]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [269953:157912430]
:KUBE-EXTERNAL-SERVICES - [0:0]
:KUBE-FIREWALL - [0:0]
:KUBE-FORWARD - [0:0]
:KUBE-KUBELET-CANARY - [0:0]
:KUBE-PROXY-CANARY - [0:0]
:KUBE-SERVICES - [0:0]
-A INPUT -j KUBE-FIREWALL
  • (9)如果获取失败则打印日志信息。如果获取成功,则从proxier.existingFilterChainsData中获取ChainLine,存入到existingFilterChains中,其中key值为Chain名字,value为该行的值(比如:KUBE-SERVICES - [0:0])
  • (10)构建existingNATChains map,清理proxier的iptablesData。
  • (11)调用SaveInto方法,将NAT表内的信息写入到proxier的iptablesData。(底层调用的命令:iptables-save -t nat)
  • (12)如果获取失败则打印日志信息。如果获取成功,则从proxier.iptablesData中获取ChainLine,存入到existingNATChains中,其中key值为Chain名字,value为该行的值(比如:KUBE-SERVICES - [0:0])
  • (13)清理proxier.filterChains、proxier.filterRules、proxier.natChains及natRules.
  • (14)往proxier.filterChains写入表头即*filter
  • (15)往proxier.natChains写入表头即*nat
  • (16)遍历filter表中的Jump链名字(KUBE-SERVICES、KUBE-EXTERNAL-SERVICES、KUBE-FORWARD),如果existingFilterChains中存在该名字,则将其对应的行信息写入到proxier.filterChains,如果不存在(考虑获取proxier.existingFilterChainsData失败),则构建对应的ChainLine写入到proxier.filterChains中。(此时,proxier.filterChains包含了KUBE-SERVICES、KUBE-EXTERNAL-SERVICES以及KUBE-FORWARD链行信息)
  • (17)遍历nat表中的Jump链名字(KUBE-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING、KUBE-MARK-MASQ),如果existingNatChains中存在,则将其对应的行信息写入到proxier.natChains,如果不存在(考虑获取proxier.existingNatChainsData失败),则构建对应的ChainLine写入到proxier.natChains中。(此时,proxier.natChains包含了KUBE-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING以及KUBE-MARK-MASQ链信息)
  • (18)构建masqRule(该规则负责匹配带有0x4000/0x4000 mark的数据包,将其交给MASQUERADE处理)
masqRule := []string{
		"-A", string(kubePostroutingChain),
		"-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`,
		"-m", "mark", "--mark", proxier.masqueradeMark,
		"-j", "MASQUERADE",
	}
# 其中:
# kubePostroutingChain:KUBE-POSTROUTING
# masqueradeMark:由--iptables-masquerade-bit决定,
masqueradeValue = 1 << uint(14)
masqueradeMark = fmt.Printf("%#08x/%#08x", masqueradeValue, masqueradeValue)
--iptables-masquerade-bit默认为14,这则masqueradeMark默认为0x4000/0x4000

# iptables nat表中对应的规则
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
# 可以通过该命令查看 
iptables -t nat -L KUBE-POSTROUTING 
  • (19)如果iptables支持RandomFully(iptables版本大于1.6.2,参考iptables.go)。则在masqRule中添加–random-fully参数(避免linux内核问题,多个流映射到相同的IP:PORT)
  • (20)将masqRule加入到proxier.natRules中。
  • (21)向proxier.natRules中,加入set-xmark规则
writeLine(proxier.natRules, []string{
		"-A", string(KubeMarkMasqChain),
		"-j", "MARK", "--set-xmark", proxier.masqueradeMark,
	}...)
其中:
KubeMarkMasqChain:KUBE-MARK-MASQ
proxier.masqueradeMark:默认为0x4000/0x4000
# 可以通过该命令查询
iptables -t nat -L KUBE-MARK-MASQ
  • (22)构建activeNATChains map,其累积需要保存的NAT链
  • (23)构建replacementPortsMap,累积一旦更新完成,我们将保持打开的本地端口集
  • (24)构建空endpoints信息及endpointChains slice。
  • (25)置proxier.endpointChainsNumber为0, 通过遍历proxier.serviceMap,累加所有serviceName对应的endpointsMap长度,获取proxier.endpointChainsNumber值
  • (26)遍历service,为每个service构建规则
    • 1)获取svcInfo(包括了svc的基础信息,以及serviceNameString、servicePortChainName、serviceFirewallChainName、serviceLBChainName )
      • a)servicePortChainName: KUBE-SVC-svc端口名字(namespace + name + portname)及协议Hash
      • b)serviceFirewallChainName:KUBE-FW-svc端口名字及协议Hash
      • c)serviceLBChainName: KUBE-XLB–svc端口名字及协议Hash
    • 2)判读clusterIP类型
    • 3)获取svcInfo协议类型(TCP or UDP or SCP)
    • 4)获取svcName对应的endpoints,记为allEndpoints
    • 5)基于allEndpoings,获取hasEndpoints属性
    • 6)如果有endpoints,则判断当前svcInfo对应的svcChain是否在existingNATChains中,如果时,将对应行信息写入到proxier.natChains中。否则构建对应svcChainLine.并在activeNATChains中记录该chain( existingNATChains中的行信息基于iptables-save -t nat生成,比如:KUBE-SVC-5SLFW5ITLOQQHB35 - [0:0])
    • 7)如果service是LB或NodePort类型Service,且service.Spec.ExternalTrafficPolicy为Local,即转发时,只允许转发给本地容器,保证源IP地址不变,则判断svcInfo对应serviceLBChainName是否已经存在,如果存在则将行信息写入到proxier.natChains,否则构建新的写入到proxier.natChains,同时在activeNATChains中记录该chain。
    • 8)如果有endpoints,构建该svc的masquerad规则(追加到KUBE-SERVICES链,匹配规则为目的IP为ClusterIP,协议为svc协议,端口为svc端口,查询命令iptables -t nat -L KUBE-SERVICES)及跳转SVC链规则.
      • a) 如果proxier.masqueradeAll为真,则在proxier.natRules中加入该svc的masquerad规则,目的链为KUBE-MARK-MASQ.
      • b) 如果不为真,且kube-proxy在启动时配置了启动参数–cluster-cidr(cluster-cidr主要用于帮助 kube-proxy 区分内外流量。当值为空时,kube-proxy认为所有流量都是内部流量,不做SNAT(MASQ)即c情况。当值非空时,来自 cluster-cidr 网络(即 Pod网络)的流量被当成内部流量,访问 Service 时不做 SNAT(MASQ),来自其他网络的流量被当成外部流量,访问 Service 时需要做 SNAT(MASQ),如果配置了masqueradeAll,则所有流量都要做SNAT),则在匹配规则中额外添加源地址不允许是proxier.clusterCIDR(该规则将非cluster IP流量masquerades到一个service VIP。这么做可以通过为Sevice Ranage建立静态路由,将流量路由到任意节点,而该节点将会为你连接到Service内。因为可能会跳离节点,因此需要在这里masquerade。当我们支持"Local"策略时,应该更新它)。目的链为KUBE-MARK-MASQ**
      • c)往proxier.natRules追加KUBE-SVC-HASH(hash值基于NamespacedSVCName、PortName、Protocol计算得到)
      • d)如果不为真,且kube-proxy在启动时没有配置启动参数–cluster-cidr,则目的链为svcChain(这种情况认为所有的流量都是内部流量,不做MASQ)
    • 9)如果没有endpoints,则往proxier.filterRules的KUBE-SERVICES链中追加REJECT规则
    • 10)遍历svcInfo中的外部IP地址。(目前我们没有使用这个字段)
      • A)如果该IP地址不是本地系统设备上的某个地址,则打印日志信息。
      • B)如果该IP地址是本地系统设备上的某个地址,且协议类型不为SCTP。
        • a)构建LocalPort lb(IP、Port、Protocol)
        • b)如果proxier.portsMap中存在该端口,更新replacementPortsMap[lb] = proxier.portsMap[lp]
        • c)如果不存在,则在本地打开端口,返回得到socket,replacementPortsMap[lb] = socket
      • C)如果有endpoints。则构建nat规则,追加到KUBE-SERVICES链表,匹配协议为svc协议,目的端口为svc端口,目的链为KUBE-MARK-MASQ。该规则负责SNAT到external IPs。构建externalTrafficOnly规则,其在上一个规则基础上增加了匹配规则,其允许非来自bridge或本地进程的流量z转发到service,即外部来的流量。构建dstLocalOnlyArgs规则,其在第一个规则基础上,增加匹配规则,允许被识别为本地ip的外部ip绑定的流量留在本地。
      • D)如果没有,则往proxier.filterRules的KUBE-SERVICES链中追加REJECT规则。
    • 11)遍历svcInfo中的LoadBalancerIPStrings,对ingress不为空的svcInfo做处理。
      • A)如果有后端。则判断对应FirewallChain名字是否在existingNATChains中存在,如果存在则写入到proxier.natChains中。否则则新建后写入(:KUBE-FW-5SQY75UPE7NMO5UB - [0:0]).并更新activeNATChains[fwChain] = true
        • b)构建nat规则,在KUBE-SERVICE链表中,追加匹配LB协议、目的IP、目的端口时,跳转入fwChain的规则。
        • c)chosenChain := svcXlbChain
        • d)构建nat规则,在fwChain中追加。如果svcInfo不是OnlyNodeLocalEndpoints,则目标链为KUBE-MARK-MASQ。chosenChain = svcChain。
        • e)如果svcInfo.LoadBalancerSourceRanges长度为0(该字段确定了可以访问LB的客户端IP),则目标链为choseChine
        • f)如果svcInfo.LoadBalancerSourceRanges长度不为0,则匹配规则为源来自oadBalancerSourceRanges,目标地址为chosenChain.
        • g)添加默认丢弃规则,KUBE-MARK-DROP
      • B)如果没有,则往proxier.filterRules的KUBE-SERVICES链中追加REJECT规则。
      1. 如果svc的NodePort不为0
      • A)基于配置,在本机设备上找到所有在proxier.nodePortAddresses(–nodeport-addresses启动参数决定)内的address。
      • B)遍历address,基于每个Address生成LocalPort对象(IP=address,Port=svcInfo.NodePort,protocol=svcInfo.protocol)。
      • C)遍历这些LocalPort对象,
        • a)如果其存在与proxier.portsMap[lp],则replacementPortsMap[lp] = proxier.portsMap[lp]。
        • b)否则当协议类型不是ProtocolSCTP时,构建对应socket,同时对于udp清理链接状态.更新replacementPortsMap[lp] = socket
        • c)如果具有endpoints,则往KUBE-NODEPORTS链添加规则。如果svcInfo不是OnlyNodeLocalEndpoints,则往proxier.natRules添加跳转到KUBE-MARK-MASQ及svcChain.否则对于源IP地址为回环地址的数据包,配置JUMP为KUBE-MARK-MASQ,其它jump到svcXlbChain.
        • c)如果没有,则往proxier.filterRules的KUBE-SERVICES链中追加REJECT规则。
      • 13)如果没有endpoints,则处理下一个svcInfo
      • 14)刷新endpoints及endpointChain链表
      • 15)遍历当前svcInfo对应的endpoints
        • A)获取epInfo(协议,chainName=KUBE-SEP-svcName+protocol+endpoint的哈希值)
        • B)将epInfo加入到endpoints slice中
        • C)构建endpointChain,并将其加入到endpointChains slice中
        • D)如果它已经存在于existingNATChains中则将其对应行信息写入到proxier.natChains中,否则构建新Chain,写入其中(:KUBE-SEP-ZM2K5WAG2QZ6VDLK - [0:0]).置activeNATChains[endpointChain] = true
      • 16)如果svcInfo.SessionAffinityType == ServiceAffinityClientIP(基于客户端源IP的亲和性)。遍历endpointChains slice,为每个endpointsChain在svcChain中添加会话保持规则。
      • 17)遍历endpointChains
        • A) 如果svcInfo.OnlyNodeLocalEndpoints为true,且当前endpoint在本机器上。则将其加入到localEndpoints,并将对应endpoinChain加入到localEndpointChains
        • B)获取EP.IP, 如果IP不存在,则跳过处理
        • C)基于endpointChain当前索引,计算其概率,构建nat规则,加入到endpointChain中(-A KUBE-SVC-PRPXIF4GQR5KDAOQ -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-N66C6CFW2S6AAC7V)。如果是最后一个endpoint,则不需要-m statistic --mode random --probability 0.50000000000配置。
        • D)往endpointChain中添加nat规则,对于源IP地址是epIP地址的数据包,跳转进入KUBE-MARK-MASQ。其用于用SNAT处理返回到发起者的通讯
        • E)如果具有客户端亲和性,则更新参数,加入亲和性配置
        • F)更新参数加入DNAT动作,往endpointChain中加入该DNAT规则(如果有客户端IP亲和性,相当于在这个规则里多加了-m recent --name endpointChain --set参数。不加情况下,规则可能为DNAT tcp – anywhere anywhere tcp to:172.20.0.22:8443)。
        • G)如果!svcInfo.OnlyNodeLocalEndpoints(),则处理下一个svcInfo
        • H)clusterCIDR大于0时,svcXlbChain中加入nat规则,对于源来自clusterCIDR的,跳入svcChain处理。(重定向尝试访问LB IP的pod,访问ClusterIP)
        • I)构建并添加重定向规则,对于externalTrafficPolicy=Local的svc,将所有src-type=Local->LB IP的数据包重顶下到svcChain.
        • J)如果本地的localEndpointChains等于0,则往svcXlbChain中添加规则,跳转到KUBE-MARK-DROP,即该机器上没有这个svc的pod,而这个pod又不允许转发到别的节点,因此就丢弃了。
        • K)否则,在svcXlbChain 为local endpoints添加robability filter rules
  • 27)遍历existingNATChains,对于非激活链,且由kube-proxy构建的,往proxier.natRules中添加删除规则
  • 28)如果在本机设备存在NodePort地址,则为这些地址在KUBE-SERVICES链中添加nat规则,对于目的地址类型为本地的地址,跳入KUBE-NODEPORTS处理。
  • 29)构建filter规则,往KUBE-FORWARD链中增加状态为INALID的数据包的丢包处理规则
  • 30)构建filter规则,往KUBE-FORWARD链中增加mark为proxier.masqueradeMark的数据包的接收处理规则。
  • 31)如果proxier.clusterCIDR长度大于0。
    • A)构建filter规则,往KUBE-FORWARD链中添加,对于源IP是proxier.clusterCIDR,或者与其相关的,数据包Accept规则。
    • B)构建filter规则,往KUBE-FORWARD链中添加,对于目的IP是proixer.clusterCIDR,或者与其相关的,数据包Accept规则。
  • 32)清理proxier.iptablesData,往其中写入proxier.filterChains.Bytes()、proxier.filterRules.Bytes()、proxier.natChains.Bytes()、proxier.natRules.Bytes()。
  • 33)重新存储iptables data
  • 34)更新指标及健康检查信息
  • 35)清理无效UDP链接信息。

6 数据包路径及链位置

在这里插入图片描述

 kube-proxy在开始下发svc\ep相关规则前,会现往filter表追加KUBE-SERVICES、KUBE-EXTERNAL-SERVICES、KUBE-FORWARD链跳转规则,会往nat表追加入KUBE-SERVICES、KUBE-NODEPORTS、KUBE-POSTROUTING、KUBE-MARK-MASQ链跳转规则。并为KUBE-POSTROUTING及KUBE-MARK-MASQ链添加默认规则。

# KUBE-POSTROUTING
# Add Rule
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING

# Show Rule
iptables -t nat -L KUBE-POSTROUTING

# Show Result
Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination         
MASQUERADE  all  --  anywhere             anywhere             /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000

-----------------------------------------------------------------------------------

# KUBE-MARK-MASQ
# Add Rule
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE

# Show Rule
iptables -t nat -L KUBE-MARK-MASQ

# Show Result
Chain KUBE-MARK-MASQ (63 references)
target     prot opt source               destination         
MARK       all  --  anywhere             anywhere             MARK or 0x4000

6.1 PREROUTING

6.1.1 PREROUTING ->KUBE-SERVICES

NAT表的PREROUTING链中加入了,KUBE-SERVICES链跳转规则。对于所有的数据包,跳转入KUBE-SERVICES链处理

# Add Rule
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES

# Show Rule
iptables -t nat -L PREROUTING

# Show Result 
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */

6.1.2 KUBE-SERVICES

数据包经过NAT表PREROUTING链中规则匹配,进入KUBE-SERVICE链处理

6.1.2.1 ClusterIP

6.1.2.1.1 KUBE-SERVICES->KUBE-MARK-MASQ

kube-proxy会遍历每个svcInfo,根据clusterIP、启动参数–cluster-cidr及–masquerade-all来配置, jump到KUBE-MARK-MASQ链的匹配规则。

  • (1) 配置了–masquerade-all,认为所有流量都是外部流量,都要打标签
# Add Rule
-A KUBE-SERVICES -d 10.68.81.30/32 -p tcp -m comment --comment "demo/s-test-mq:tcp-5672 cluster IP" -m tcp --dport 5672 -j KUBE-MARK-MASQ
  • (2)–cluster-cidr不为空,认为–cluster-cidr指定网段为内部网段不需要打标签,其它流量为外部流量需要打标签
# Add Rule
-A KUBE-SERVICES ! -s 172.20.0.0/16 -d 10.68.81.30/32 -p tcp -m comment --comment "demo/s-test-mq:tcp-5672 cluster IP" -m tcp --dport 5672 -j KUBE-MARK-MASQ
  • (3)–cluster-cidr为空,认为所有流量都是内部流量,都不打标签,在POSTROUTING时,不需要SNAT

KUBE-MARK-MASQ链内规则会为进入链的所有数据包打上0x4000/0x4000标签(进行完此处理动作后,将会继续比对其它规则)

# Show Rule
iptables -t nat -L KUBE-MARK-MASQ

# Show Result
Chain KUBE-MARK-MASQ (63 references)
target     prot opt source               destination         
MARK       all  --  anywhere             anywhere             MARK or 0x4000
6.1.2.1.2 KUBE-SERVICES->KUBE-SVC-HASH

kube-proxy会在KUBE-SERVICES中为每个具有clusterIP的 svcPort构建KUBE-SVC-HASH跳转规则,将访问svcPort的数据包,导入到KUBE-SVC-HASH链中

# Add Rule
-A KUBE-SERVICES -d 10.68.249.16/32 -p tcp -m comment --comment "demo/netutil-2:tcp-8081 cluster IP" -m tcp --dport 8081 -j KUBE-SVC-QUZXUNUIPD3MZETI

# Show Rule
KUBE-SVC-QUZXUNUIPD3MZETI  tcp  --  anywhere             10.68.249.16         /* demo/netutil-2:tcp-8081 cluster IP */ tcp dpt:tproxy

6.1.2.2 External IP

对于External IP,只有当前物理机上设备有这个地址时,kube-proxy才会下发规则.kube-proxy首先在本地使用External IP及svcPort、Protocol打开一个端口,然后下发规则。

6.1.2.2.1 KUBE-SERVICES->KUBE-MARK-MASQ

kube-proxy会在KUBE-SERVICES内,为每个External IP添加KUBE-MARK-MASQ跳转规则,对于目的地址为External IP的数据包丢入KUBE-MARK-MASQ打mark

# 查询
iptables-save -t nat | grep external 

# Add rule
-A KUBE-SERVICES -d 公网IP地址 /32 -p tcp -m comment --comment "demo/hk-nginx-hello:tcp-80 external IP" -m tcp --dport 80 -j KUBE-MARK-MASQ

# 查询
iptables -t nat  -L KUBE-SERVICES | grep "external IP" | grep MARK
 
# 结果
KUBE-MARK-MASQ  tcp  --  anywhere  地址这里显示的主机名  /* demo/hk-nginx-hello:tcp-80 external IP */ tcp dpt:http

6.1.2.2.2 KUBE-SERVICES->KUBE-SVC-HASH

kube-proxy会在KUBE-SERVICES内,为每个External IP添加KUBE-SVC-HASH跳转规则

# Add rule
-A KUBE-SERVICES -d 公网IP地址 /32 -p tcp -m comment --comment "demo/hk-nginx-hello:tcp-80 external IP" -m tcp --dport 80 -m physdev ! --physdev-is-in -m addrtype ! --src-type LOCAL -j KUBE-SVC-UEOQSLEZ4LUM4H7G
-A KUBE-SERVICES -d 公网IP地址 /32 -p tcp -m comment --comment "demo/hk-nginx-hello:tcp-80 external IP" -m tcp --dport 80 -m addrtype --dst-type LOCAL -j KUBE-SVC-UEOQSLEZ4LUM4H7G

# show rule
 iptables -t nat  -L KUBE-SERVICES | grep "external IP" | grep -v MARK

# 非本地请求,转发到svc
KUBE-SVC-UEOQSLEZ4LUM4H7G  tcp  --  anywhere  地址这里显示的主机名  /* demo/hk-nginx-hello:tcp-80 external IP */ tcp dpt:http PHYSDEV match ! --physdev-is-in ADDRTYPE match src-type !LOCAL

# 本地请求转发到svc
KUBE-SVC-UEOQSLEZ4LUM4H7G  tcp  --  anywhere  地址这里显示的主机名  /* demo/hk-nginx-hello:tcp-80 external IP */ tcp dpt:http ADDRTYPE match dst-type LOCAL

6.1.2.3 LB IP

6.1.2.3.1 KUBE-SERVICES->KUBE-FW-HASH

kube-proxy会为每个具有LB IP的svcPort构建KUBE-FW-HASH跳转规则,将访问LBIP:svcPort(协议+端口)的数据包,导入到KUBE-FW-HASH链中

# Add Rule
-A KUBE-SERVICES -d 公网IP地址 /32 -p tcp -m comment --comment "demo/netutil-2:tcp-8081 loadbalancer IP" -m tcp --dport 8081 -j KUBE-FW-QUZXUNUIPD3MZETI

# Show Rule
KUBE-FW-QUZXUNUIPD3MZETI  tcp  --  anywhere             公网IP地址       /* demo/netutil-2:tcp-8081 loadbalancer IP */ tcp dpt:tproxy
6.1.2.3.2 KUBE-FW-HASH->KUBE-MARK-MASQ

对于进入KUBE-FW-HASH链的所有数据包进入KUBE-MARK-MASQ,打上0x4000/0x4000标记

6.1.2.3.3 KUBE-FW-HASH->KUBE-SVC-HASH

打完MASQ的数据包,进入链表KUBE-SVC-QUZXUNUIPD3MZETI处理(如果这个时候有后端,会把数据包按概率丢给链KUBE-SVC-QUZXUNUIPD3MZETI-HASH处理)

# Show Rule
iptables -t nat -L KUBE-FW-QUZXUNUIPD3MZETI

# Show Rule
Chain KUBE-FW-QUZXUNUIPD3MZETI (1 references)
target     prot opt source               destination         
KUBE-MARK-MASQ  all  --  anywhere             anywhere             /* demo/netutil-2:tcp-8081 loadbalancer IP */
KUBE-SVC-QUZXUNUIPD3MZETI  all  --  anywhere             anywhere             /* demo/netutil-2:tcp-8081 loadbalancer IP */
KUBE-MARK-DROP  all  --  anywhere             anywhere             /* demo/netutil-2:tcp-8081 loadbalancer IP */
6.1.2.3.4 KUBE-FW-HASH->KUBE-MARK-DROP

对于没有endpoint的数据包,不会在KUBE-SVC-HASH中匹配,进入KUBE-MARK-DROP链表处理,会打上0x8000/0x8000标记(这些数据包会在filter被过滤丢弃)

6.1.2.4 NodePort

6.1.2.4.1 KUBE-SERVICES->KUBE-NODEPORTS

kube-proxy会在KUBE-SERVICES链中构建KUBE-NODEPORTS链,将不匹配ClusterIP、LB规则的数据包导入到KUBE-NODEPORTS链中处理

iptables -t nat -L KUBE-SERVICES| grep KUBE-NODEPORTS
6.1.2.4.2 KUBE-NODEPORTS->KUBE-MARK-MASQ

kube-proxy在KUBE-NODEPORTS中添加规则,匹配目标端口是否为NodePort,如果是,将数据包导入KUBE-NODEPORTS,打上MASQ标记

6.1.2.4.3 KUBE-NODEPORTS->KUBE-SVC-HASH

kub-proxy在KUBE-NODEPORTS中添加规则,匹配目标端口是否为NodePort,如果是将数据包导入到KUBE-SVC-HASH链处理

iptables -t nat -L KUBE-NODEPORTS

6.1.2.5 KUBE-SVC-HASH -> KUBE-SEP-HASH

kube-proxy会在KUBE-SVC-HASH链内为svcPort的每个endpoint构建基于概率的 KUBE-SEP-HASH跳转规则,并为每个endpoint构建KUBE-SEP-HASH规则

# Add Rule
-A KUBE-SVC-QUZXUNUIPD3MZETI -m statistic --mode random --probability 0.33333333349 -j KUBE-SEP-AMWXJCMBQ4RG26Q5
-A KUBE-SVC-QUZXUNUIPD3MZETI -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-2OQUDCMHKG5JUGZU
-A KUBE-SVC-QUZXUNUIPD3MZETI -j KUBE-SEP-Z2UJWNX76VNMX7FW

# Rule show 
iptables -t nat -L KUBE-SVC-QUZXUNUIPD3MZETI

# Show Result 
Chain KUBE-SVC-QUZXUNUIPD3MZETI (2 references)
target     prot opt source               destination         
KUBE-SEP-AMWXJCMBQ4RG26Q5  all  --  anywhere             anywhere             statistic mode random probability 0.33333333349
KUBE-SEP-2OQUDCMHKG5JUGZU  all  --  anywhere             anywhere             statistic mode random probability 0.50000000000
KUBE-SEP-Z2UJWNX76VNMX7FW  all  --  anywhere             anywhere  

6.1.2.6 KUBE-SEP-HASH

  • (1)对于源IP地址为172.20.4.10的数据包进行MARK。endPoint 访问SVC的情况。
  • (2)对数据包进行DNAT,将目的IP地址从Service CluterIP NAT为Pod IP
# Add Rule
-A KUBE-SEP-AMWXJCMBQ4RG26Q5 -s 172.20.4.10/32 -j KUBE-MARK-MASQ
-A KUBE-SEP-AMWXJCMBQ4RG26Q5 -p tcp -m tcp -j DNAT --to-destination 172.20.4.10:8091

# Show Rule
iptables -t nat -L KUBE-SEP-AMWXJCMBQ4RG26Q5

# Show Result
Chain KUBE-SEP-AMWXJCMBQ4RG26Q5 (1 references)
target     prot opt source               destination         
KUBE-MARK-MASQ  all  --  172.20.4.10          anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp to:172.20.4.10:8091

6.2 INPUT

FILTER 表的INPUT链中配置了KUBE-SERVICES, KUBE-EXTERNAL-SERVICES 跳转规则(KUBE-SERVICES未命中,再匹配KUBE-EXTERNAL-SERVICES)。

iptables -t filter -L INPUT

6.2.1 FILTER INPUT ->KUBE-SERVICES

拒绝目的地址为指定IP的数据包(这些IP对应的Service没有endpoints,这里的目的IP可能是Cluter IP、LB IP)

# Show Rules
iptables -t filter -L KUBE-SERVICES

# Show Result
Chain KUBE-SERVICES (3 references)
target     prot opt source               destination         
REJECT     tcp  --  anywhere             10.68.236.66         /* default/myservice: has no endpoints */ tcp dpt:ssh reject-with icmp-port-unreachable
REJECT     tcp  --  anywhere             10.68.121.211        /* demo/test-lb:tcp-80 has no endpoints */ tcp dpt:http reject-with icmp-port-unreachable
REJECT     tcp  --  anywhere             公网IP地址      /* demo/test-lb:tcp-80 has no endpoints */ tcp dpt:http reject-with icmp-port-unreachable
REJECT     tcp  --  anywhere             10.68.220.136        /* demo/test3:tcp-80 has no endpoints */ tcp dpt:http reject-with icmp-port-unreachable
REJECT     tcp  --  anywhere             公网IP地址       /* demo/test3:tcp-80 has no endpoints */ tcp dpt:http reject-with icmp-port-unreachable

6.2.2 FILTER INPUT ->KUBE-EXTERNAL-SERVICES

拒绝目的地址为指定External IP的数据包(这些IP对应的Service没有endpoints,这里的IP可能是External IP、Node IP)

iptables -t filter -L KUBE-EXTERNAL-SERVICES

6.3 FORWARD

FILTER 表的FORWARD链中配置了KUBE-FORWARD, KUBE-SERVICES 跳转规则(KUBE-FORWARD未命中,再匹配KUBE-SERVICES)。

iptables -t filter -L FORWARD

6.3.1 FORWARD-> KUBE-FORWARD

  • (1)丢弃处于状态处于INVALID的数据包,因为它可能会潜在导致不期望的链接重置
  • (2)转发所有打了0x4000/0x4000标记的数据包
  • (3)后两条规则确保在“kubernetes kubernetes forwarding rules"”接受的初始数据包之后的流量将被接受,尽可能具体地说,流量必须来源于或指向clusterCIDR(到/从一个pod), 即保证Pod流量可以被转发(该规则再配置了–cluster-cidr时配置)。
# Show Rules
iptables -t filter -L KUBE-FORWARD

# Show Result
Chain KUBE-FORWARD (1 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere             ctstate INVALID
ACCEPT     all  --  anywhere             anywhere             /* kubernetes forwarding rules */ mark match 0x4000/0x4000
ACCEPT     all  --  172.20.0.0/16        anywhere             /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             172.20.0.0/16        /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHE

6.3.2 FORWARD-> KUBE-SERVICES

拒绝目的地址为指定IP的数据包(这些IP对应的Service没有endpoints,这里的目的IP可能是Cluter IP、LB IP)

6.4 OUTPUT

NAT 表及Filter表中添加了KUBE-SERVICE链表跳转规则。数据包先过NAT链,再过Filter链。

6.4.1 NAT OUTPUT-> KUBE-SERVICES

所有数据包进入NAT表的KUBE-SERVICES链处理,KUBE-SERVICES链处理流程和6.1从NAT 表PreRouting 链进入NAT表一致。

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */

6.4.2 NAT OUTPUT-> KUBE-SERVICES

数据包进入Filter表的KUBE-SERVICES,KUBE-SERVICES链处理流程和6.2.1 Filter INPUT进入KUBE-SERVICES一致。

6.5 POSTROUTING

kube-proxy在NAT 表的POSTROUTING链中加入了KUBE-POSTROUTING跳转链表规则

-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING

6.5.1 NAT POSTROUTING -> KUBE-POSTROUTING

KUBE-POSTROUTING 链表中对于打了0x4000/0x4000标签的数据包,进行MASQUERADE,进行SNAT。

# Add Rule
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE

# Show Rule
iptables -t nat -L KUBE-POSTROUTING

# Show Result
Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination         
MASQUERADE  all  --  anywhere             anywhere             /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000

7 总结

入包处理整体流程(进入主机)

  • (1)Nat表PreRouting、OutPut拦截所有数据包进入KUBE-SERVICE链处理
  • (2)对出包时需要SNAT的数据包打mark
  • (3)对数据包基于目的地址及目的端口进行匹配,进入KUBE-SVC-HASH链处理
  • (4)进入KUBE-SVC-HASH链,基于概率进入KUBE-SEP-HASH链,进行DNAT,将目的地址转换为RIP:RPORT

出包处理整体流程(出主机)

  • (1)Nat表PostRouting拦截所有进入KUBE-POSTROUTING链处理
  • (2)KUBE-POSTROUTING链对于打了标记的数据包,进行SNAT处理
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

kube-proxy源码阅读(iptables实现) 的相关文章

  • 通过 SOCKS 代理使用 Hadoop?

    所以我们的Hadoop集群运行在一些节点上 并且只能从这些节点访问 您可以通过 SSH 连接到它们并完成您的工作 因为这很烦人 但 可以理解 没有人会尝试配置访问控制 以便某些人可以从外部使用它 我正在尝试下一个最好的方法 即使用 SSH
  • 使用简单 PHP 代理的跨域 getJson 请求

    您好 我正在尝试从仅返回 JSON 而不是 JSONP 的 api 获取数据 每次我尝试以 JSONP 方式连接数据时 它都不起作用 因为我不期望 JSON 所以 我想我必须使用 PHP 代理来解决跨域问题 以便我可以解释 JSON 请求
  • 在 Firefox 或我的代理中禁用 websocket

    我已将 Firefox 配置为使用我的 http 和 https 代理 是的 我自己编写代理代码 因此我可以完全控制代理 您可能知道 无法再通过 about config 在 Firefox 中禁用 WebSocket 我正在寻找一种轻量级
  • 从 apache 到 IIS 的反向代理总是失败并显示 404

    我正在尝试设置从 apache 到 IIS 7 服务器的反向代理 我已经设置了非常基本的代理规则
  • Proxifier 是如何工作的?

    如你所知Proxifier是一个程序 允许不支持通过代理服务器工作的网络应用程序通过 HTTPS 或 SOCKS 进行操作 它可以处理来自正在运行的应用程序的任何传输 我想知道它是如何做到这一点以及我如何写一个这样的 FreeCap htt
  • 如何在 SWIFT 3 中将 HTTPS 代理添加到 NSURLSession

    我使用以下代码连接到代理服务器 并且仅适用于 HTTP 请求 但不适用于 HTTPS 在 iOS 9 0 中 kCFStreamPropertyHTTPSProxyHost and kCFStreamPropertyHTTPSProxyPo
  • 在Ubuntu 18.04、Python 3.6.7 64位、Mono 5.16上安装pythonnet失败

    我想在 Ubuntu 上安装 pythonnet 但失败了 这就是我到目前为止所尝试的 usr bin python3 m pip install U pythonnet user Error Collection pythonnet Us
  • 是否可以通过 FTP 代理使用 C# FtpWebRequest?

    据我了解 FtpWebRequest Proxy属性表示 HTTP 代理 我必须通过 FTP 代理向外部服务器发出 FTP 请求 到目前为止 我实现此功能的唯一方法是创建一个使用 Windows FTP 命令的脚本并以这种方式下载 是否可以
  • 查找通过代理连接的客户端的IP地址

    有没有办法收集通过代理服务器连接到您网站的客户端的 IP 地址 整个设置是一个内部 LAN 通过系统管理员 我也可以控制代理计算机 我在网站服务器端使用 PHP5 I tried SERVER REMOTE ADDR 在 PHP 中 但此变
  • $Proxy$_$$_Weld$EnterpriseProxy$ 代理子类是如何实现的?

    在 Java EE 7 应用程序中 假设我有一个会话 bean 类 Stateless public class MyEJB 在 Glassfish 4 下调试时 我可以看到一个名为MyEJB Proxy Weld EnterprisePr
  • Axis HTTP 与 Axis HTTPS 代理设置

    我部署在 Weblogic 集群上的 Java 应用程序调用两个 Web 服务 如下所示 它通过 HTTPS 将 SOAP 客户端请求发送到互联网上的外部应用程序 通过 Axis 1 4 创建的 Java 类 此后 它通过 HTTP 将 S
  • 使用 Flask 代理到另一个 Web 服务

    我想将对 Flask 应用程序发出的请求代理到计算机上本地运行的另一个 Web 服务 我宁愿使用 Flask 而不是更高级别的 nginx 实例 这样我们就可以重用应用程序中内置的现有身份验证系统 我们越能保持这种 单点登录 越好 是否有现
  • Squid - 监听多个端口并转发到不同的代理

    我想设置一个侦听多个端口的代理 每个端口将请求转发到不同的代理 例如 LISTEN FORWARD TO 1 2 3 4 3128 gt 5 6 7 8 3128 1 2 3 4 3129 gt 5 6 7 9 3128 1 2 3 4 3
  • 如果 OSX/iOS 中的网络代理设置发生更改,是否有办法接收通知/回调?

    如果 OSX iOS C C 或 Objective C 中的网络代理设置发生更改 我想收到通知 回调吗 有人有关于如何执行此操作的示例吗 监控系统配置SCDynamicStoreSetNotificationKeys 对于您需要注意的按键
  • 如何从 .pac 文件中查找代理服务器和密码

    我正在使用 dynatrace ajax 版本 它需要代理服务器和密码才能连接到 dynatrace 服务器 问题是我只有我们在工作中使用的 pac 文件 URL 是否可以知道我的请求解析到哪个代理服务器和端口 以便我可以直接提供代理服务器
  • 无法拦截来自 Nike.com 登录请求的流量

    我正在使用 BurpSuite 拦截登录时发送的 HTTP HTTPS 请求https www nike com https www nike com 我试图通过以下步骤来实现这一目标 打开 BurpSuite 和 Firefox 开启代理
  • 除了 iptables 之外还有数据包管理实用程序吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 Linux 实用程序 它可以根据一组规则更改网络数据包的有效负载 理想情况下 我会使用
  • Windows 注册表中的 DefaultConnectionSettings 值的格式是什么?

    Windows 注册表项 HKCU Software Microsoft Windows CurrentVersion Internet Settings Connections 包含一个名为的二进制值DefaultConnectionSe
  • C#中如何通过Proxy访问互联网

    我正在使用 C 设计一个 Windows 窗体应用程序 当连接到互联网时 该应用程序可以顺利执行其功能 但当我们在学院尝试该应用程序时 真正的问题就开始了 我们的学院使用代理网关连接到网络 代理服务器是192 168 120 5和代理端口8
  • 使用 Connect 和 node-http-proxy 的 HTTP 代理

    在开发过程中 我需要一个 HTTP 代理来访问外部 API 以绕过跨域安全限制 我在这里找到了一些示例代码 http nthloop com blog local dev with nodejs proxy http nthloop com

随机推荐

  • Spring中的 JdbcTemplate和声明式事务控制

    Spring中的 JdbcTemplate和声明式事务控制 JdbcTemplate概述 JdbcTemplate的作用 xff1a 他就是用于和数据库交互的 xff0c 实现CRUD操作 如何创建该对象 在dao的实现类中定义并用set方
  • SpringMVC(一)

    SpringMVC xff08 一 xff09 SpringMVC的基本概念 三层架构 表现层业务层持久层 MVC模型 Model xff08 模型 xff09 xff1a 通常就是指我们的数据模型 xff0c 一般情况下用于封装数据 Vi
  • SpringMVC(二)

    SpringMVC xff08 二 xff09 响应数据和结果视图 返回值分类 xff1a 字符串voidModelAndView 对象 xff1a 是 spring 提供的一个对象 xff0c 可以用来调整具体的 JSP 视图 span
  • SpringMvc(三)

    SpringMvc xff08 三 xff09 SSM 整合可以使用多种方式 xff0c 一般会选择 XML 43 注解 的方式 整合的思路 xff1a 搭建整合环境先把spring 的配置搭建完成再使用 spring 整合SpringMV
  • 工厂方法模式(Factory Method)--多态工厂的实现

    工厂方法模式 xff08 Factory Method xff09 多态工厂的实现 定义 xff1a 定义一个用于创建对象的接口 xff0c 让子类决定实例化哪一个类 xff0c 工厂方法使一个类的实例化延迟到其子类 类图 xff1a 外链
  • 无人机自主定位导航避障VINS+fast_planner实测~

    厦大研一研究的一个项目 xff0c 将项目开发用到的技术和难点在这记录一下 常更新 xff0c 先把框架写好 xff0c 有空的时候就过来更新 xff0c 要是有漏的或者有错误的地方 xff0c 请大佬指点 因为采用的是TX2 xff0c
  • rs_D455相机内外参标定+imu联合标定

    IMU标定 lt launch gt lt node pkg 61 34 imu utils 34 type 61 34 imu an 34 name 61 34 imu an 34 output 61 34 screen 34 gt lt
  • GVINS论文简明解读

    VIN与GNSS融合的必要性 VIN系统只工作在局部坐标系下 x y z yaw不可观 里程计存在不可避免的漂移 而GNSS系统可提供无漂移的全局定位 VIN与GNSS融合的难点 不同于cmaera与imu此类的外参标定 GNSS坐标与VI
  • onos2.5.2编译安装

    onos编译安装 Ubuntu18 04 1 前置下载安装 1 1 前置包安装 参考docker file sudo apt get install y ca certificates zip python python3 git bzip
  • C++和C的区别(汇总)

    1 C是面向过程的语言 xff0c 而C 43 43 是面向对象的语言 2 C和C 43 43 动态管理内存的方法不一样 xff0c C是使用malloc free函数 xff0c 而C 43 43 除此之外还有new delete关键字
  • PX4学习笔记—通过串口发送自定义数据

    最近因为项目需要实现一个通过pixhawk串口收发自定义数据的功能 搜索发现 xff0c 博客上大神们FantasyJXF FreeApe的博文已经详细介绍了通过pixhawk串口读取自定义数据 xff0c 这部分功能实现后就可以将自己开发
  • 一步步入门搭建SpringSecurity OAuth2(密码模式)

    什么是OAuth2 xff1f 是开放授权的一个标准 xff0c 旨在让用户允许第三方应用去访问改用户在某服务器中的特定私有资源 xff0c 而可以不提供其在某服务器的账号密码给到第三方应用 大概意思就是比如如果我们的系统的资源是受保护的
  • STM32驱动SG90舵机与HC_SR04超声波模块

    前言 一 项目涉及的内容 项目简介 二 模块实操 1 SysTick系统定时器模块 2 SG90 舵机模块 3 HC SR04 超声波模块 4 main函数 总结 前言 这篇文章的内容主要对一个超声波 43 舵机小项目进行总结 xff0c
  • STM32基于IIC协议的OLED模块的使用

    前言 一 项目涉及的内容 项目简介 二 模块实操 1 IIC模块 1 1 IIC协议格式 1 2 开始信号与停止信号 1 3 写数据 1 3 1 硬件IIC代码编写 1 3 2 软件模拟IIC代码编写 2 OLED板块 前言 本篇文章对使用
  • STM32DMA功能详解

    目录 一 DMA的基本介绍 1 什么是DMA xff08 DMA的基本定义 xff09 2 DMA传输参数 3 DMA的主要特征 二 DMA功能框图 1 DMA请求 2 通道 3 仲裁器 三 DMA 数据配置 1 从哪里来到哪里去 外设到存
  • STM32对FreeRTOS单片机实时操作系统的移植

    前言 一 FreeRTOS是什么 二 FreeRTOS的移植 1 资料下载 2 开始移植 2 1 移植Source源码文件 2 2 添加 FreeRTOSConfig h 2 3 添加SYSTEM文件夹 2 4 复制 main c 文件进行
  • C语言 指针中的常见名称与用法

    目录 前言 一 指针是什么 二 指针与数组 数组指针 指针数组 三 指针与常量 指针常量 常量指针 四 指针与函数 指针函数 函数指针 前言 指针是C语言中大家接触的比较早但是也是内容比较多和实用的一块知识点 xff0c 之前虽然也大概知道
  • 过拟合及常见处理办法整理

    过拟合及常见处理办法整理 jingbo18的博客 CSDN博客 模型过拟合如何解决 判断方法 过拟合 xff08 over fitting xff09 xff0c 机器学习模型或者是深度学习模型在训练样本中表现得过于优越 xff0c 导致在
  • OBS 安装与考试参数设置及屏幕无法完全捕获、录屏不完整的解决方法

    目录 一 OBS 的下载与安装 二 OBS 考试参数设置 三 问题解决 xff08 1 xff09 屏幕无法完全捕获 xff08 2 xff09 录屏不完整 一 OBS 的下载与安装 官网 xff08 Open Broadcaster So
  • kube-proxy源码阅读(iptables实现)

    Reference 文章目录 1 入口2 ProxyServer创建及调用3 ProxyServer 核心调用流程3 1 func o Options Run err3 2 func o Options runLoop error3 3 f