【逗老师带你学IT】职场数据中心异地出口容灾,H3C的IP上一跳保持技术

本文介绍,如何通过IP上一跳保持的方式,使多个城市的公网出口可以同时为一台服务器提供DNAT映射,并确保回包路由正确。

一、需求背景和拓扑

开讲之前,我们模拟一个场景:

如果一家公司有多个城市的不同职场,且每个职场都有独立的公网出口。对于总部职场数据中心的服务器而言,我们自然很希望每个职场的公网出口都能作为入站pop节点,将总部服务器的端口映射给公网。
这样,一来可以增加出口的冗余性,另一方面也可以为不同地域的用户提供就近接入的pop点。

例如下图,HQ Office Datacenter内的服务器需要对外提供HTTP服务,同时我们在华南深圳,华北北京,以及海外都有职场,且具备独立公网IP。这时,我们当然希望这些不同的职场都可以作为pop节点提供公网服务。
在这里插入图片描述
读者朋友们很自然的想到,全网路由可达的情况下,每个pop点都做DNAT到同一个内网地址不就可以了嘛。但是我们仔细想一下,这里面存在几个挑战:

  1. SZ收到来自不同pop节点,源IP是公网IP的入站数据包后,回包应该如何正确的返回到不同的pop点?
  2. 如果pop点之间没有二层点到点专线,使用MPLS组网,那么如何让目的IP是公网IP的报文,穿越MPLS网络?
  3. 在解决以上两个问题的时候,如何确保内网服务器收到请求包,携带用户真实的公网IP?

二、入站DNAT(Destination Network Address Translation)

首先,这个案例中,处理入站流量,毋庸置疑的是肯定需要使用DNAT转换目的IP地址。
NAT(Network Address Translation,网络地址转换)是将IP数据报文头中的IP地址转换为另一个IP地址的过程。可以转换源IP,也可以转换目的IP,也可以二者同时转换。NAT为内网和外网之间的通信提供可一种灵活的方式。
根据转换地址的类型,可以分为

  • SNAT,源IP转换,一般用于内网用户访问公网
  • DNAT,目的IP转换,一般用于万网访问内网服务器
  • 双向NAT,顾名思义,源目IP地址同时转换

根据转换地址时的算法,可以分为

  • 静态NAT,内网-外网IP地址之间1:1绑定
  • 动态NAT,多个内网IP对应多个外网IP,并根据空余情况随机分配
  • NAPT,不仅转换IP,同时转换IP报文中的端口,并建立内外网端口映射表

以H3C和HUAWEI的产品举例,DNAT转换可以在设备接口下使用nat server特性实现。通过在NAT设备上配置nat server,建立一个或多个内网服务器内网地址和端口与外网地址和端口的映射关系,使外部网络用户能够通过配置的外网地址和端口来访问内网服务器。
以图中北京pop点配置进行举例:
北京公网IP地址段214.187.250.96/29,深圳职场内https服务器内网IP为10.153.20.25,北京深圳之间内网路由已经可达

interface GigabitEthernet1/0/1
 port link-mode route
 description Internet-CUC_87609887
 ip address 214.187.250.97 255.255.255.248
	 #接口IP地址
 nat server global 214.187.250.98 inside 10.153.20.25 counting
 	#目的IP为214.187.250.98的所有流量,全部由10.153.20.25来处理,并转换目的地址
 nat server protocol icmp global 214.187.250.99 inside 10.153.20.27 counting
	 #目的IP为214.187.250.98的ping包,DNAT之后由10.153.20.27处理
 nat server protocol tcp global 214.187.250.99 443 inside 10.153.20.27 443 counting
 	#目的IP为214.187.250.98的HTTPS请求,DNAT之后由10.153.20.27处理

其他pop节点的公网路由器,同样需要配置相似的DNAT转换,最终转发至相同的一台服务器处理流量,例如:

<BJ-08F-MDF-Core-FW>
interface GigabitEthernet1/0/1
	nat server protocol tcp global 214.187.250.99 443 inside 10.153.20.27 443 
#
<SZ-16F-MDF-Core-FW>
interface GigabitEthernet1/0/1
	nat server protocol tcp global 147.95.164.112 443 inside 10.153.20.27 443 
interface GigabitEthernet1/0/2
	nat server protocol tcp global 158.217.97.233 443 inside 10.153.20.27 443 
#
<JKT-12F-MDF-Core-FW>
interface GigabitEthernet1/0/1
	nat server protocol tcp global 101.200.35.175 443 inside 10.153.20.27 443 
#

这样,214.187.250.99147.95.164.112158.217.97.233101.200.35.175四个公网IP的https流量,最终都将指向同一台服务器。

二、纯DNAT技术面临的挑战

刚才我们解决的入站流量如何发送到服务器上的问题。现在,服务器处理了这个请求,开始要给用户回包了。
假使我们在北京pop节点收到一个来自源IP地址为8.8.8.9的用户的请求,我们画一下这个数据包的处理过程。

  • 入站时,DNAT将目的IP从公网IP转换成内网IP
  • 出站时,DNAT查询NAT会话表,将内网IP重新转换回公网IP。

北京pop节点的公网IP是214.187.250.99
服务器的内网IP是10.153.20.27

在这里插入图片描述

看起来似乎是正常的。但是这里面就遇到了我们刚才提到的三个问题

1、回包问题路由问题

深圳的服务器收到来自北京传来的源IP是公网IP的入站数据包后,进行处理,然后回包。
那么这个回包的目的IP是啥?

  • 是个公网IP!

在深圳的路由器上看,目的地址是公网IP的包应该怎么处理?

  • 应该走自身的缺省路由!

那么深圳的路由器上,缺省路由指向哪里?

  • 正常情况下应该指向深圳本地的公网!

所以,正常情况下,服务器处理完的回包,是不可能重新发回给北京的,直接从深圳本地的出口丢回公网了。这很明显不对劲吧。

2、公网IP穿越MPLS隧道问题

如果pop点之间没有二层点到点专线,使用MPLS组网。

由于MPLS组网采用的是与运营商对接BGP邻居,各个站点宣告自身的私网路由。

同时,由于运营商一般给每个站点开通的路由条目不过几百条,所以也不可能把公网路由导入到MPLS BGP路由表内。

而且,就算你把CNNIC甚至是APNIC的公网路由全部扒下来,并且运营商不限制你的路由条目。那么,你能确保这个8.8.8.9的用户,一定会从某个固定的pop点入站么?

所以在租用运营商的MPLS网络里,正常是没有公网IP路由的。那么如何让目的IP是公网IP的报文,穿越MPLS网络?

3、源IP保留问题

在解决以上两个问题的时候,其实很多读者应该会想到一个办法,那就是在入站的时候同时转换用户的源IP地址,将用户的公网源IP转换成一个私网IP,变成下面这样。
在这里插入图片描述

这样,我们将不同pop节点入站的报文,将其源IP地址转换成不同的内网IP,这样我们就可以很轻易的知道流量来自于哪个pop节点。

例如上面的图中,我们可以将源IP为10.13.0.1的请求回包,重新扔回给北京pop节点,同时在MPLS网络中穿越的时候,IP报文的源目地址都是内网IP,MPLS则可以正常按照路由表转发报文。

但是!但是!但是!
这样服务器就再也看不到用户的真实公网IP了,那么如何确保内网服务器收到请求包能携带用户真实的公网IP呢?

对了补充一句,不要说可以用策略路由。仔细想一下,策略路由虽然可以强制回包,但是如何解决MPLS穿越,以及区分不同的pop节点的问题呢?

三、路由器的IP上一跳保持技术

刚才的种种挑战,其实总结起来是一个问题。回包看路由,但是没路由!

那么有没有不看路由表,也可以智能选择回包路由的技术呢?

那肯定有啊,标题都写好了,就是IP上一跳保持技术

关于IP上一跳保持,有很多种手段,例如防火墙可以通过缓存的session表,确定一个会话的5元组信息,并反向查询入站接口。但是在没有高性能防火墙之前,网络设备如何做到回包的时候来回路径一致呢?

这时候就要谈到一个东西,IP转发表和快速转发表

1、FIB(Forwarding Information Base,IP转发表)

路由器通过路由表选择路由,把优选路由下发到FIB表中,通过FIB表指导IP报文转发。

FIB表中每条转发表项都指明了要到达某子网或某主机的报文的下一跳IP地址以及出接口。

简单来说,FIB是一个将路由表迭代计算完成之后,没有非直连下一跳的、可以明确下一跳和出接口的转发控制表。

<Sysname> display fib
Destination count: 4 FIB entry count: 4
Flag:
  U:Useable   G:Gateway   H:Host   B:Blackhole   D:Dynamic   S:Static
  R:Relay     F:FRR
Destination/Mask   Nexthop         Flag     OutInterface/Token       Label

10.2.0.0/16        10.2.1.1        U        GE1/0/1                  Null
10.2.1.1/32        127.0.0.1       UH       InLoop0                  Null
127.0.0.0/8        127.0.0.1       U        InLoop0                  Null
127.0.0.1/32       127.0.0.1       UH       InLoop0                  Null

2、IP FFT(IP Fast Forwarding Table ,IP快速转发表)

快速转发使用5元组(源IP地址、源端口号、目的IP地址、目的端口号、协议号)来标识一条数据流。

当一条数据流的第一个报文通过查找FIB表转发后,在高速缓存中生成相应的转发信息,该数据流后续报文的转发就可以通过直接查找快速转发表进行转发。这样便大大缩减了IP报文的排队流程,减少报文的转发时间,提高IP报文的转发速率。

如下表,访问10.153.20.27服务器的流量,在入站时,FFT表中已经记录下来不同公网IP的流量是从哪个端口进来的。此表正好可以用于回包的时候,查询该从哪个口扔出去。

<SZ-10F-MDF-Core-FW>display ip fast-forwarding cache
Total number of fast-forwarding entries: 127446
Source IP       SPort  Destination IP   DPort Pro Input_If     Output_If    Flg
103.118.48.112  51754  10.153.20.27     443   6   RAGG10       RAGG50.4000  0    
112.95.224.94   55190  10.153.20.27     443   6   RAGG10       RAGG50.4000  0    
112.82.89.37    22752  10.153.20.27     443   6   RAGG10       RAGG50.4000  1    
14.127.83.81    6248   10.153.20.27     443   6   RAGG60.4002  RAGG50.4000  0       
117.136.33.185  29324  10.153.20.27     443   6   RAGG40       RAGG50.4000  1    
112.82.89.37    24701  10.153.20.27     443   6   RAGG60.4003  RAGG50.4000  0    
112.82.89.37    25194  10.153.20.27     443   6   RAGG10       RAGG50.4000  1    
14.154.29.33    24511  10.153.20.27     443   6   RAGG60.4002  RAGG50.4000  0    
113.116.23.122  59620  10.153.20.27     443   6   RAGG30       RAGG50.4000  0    
103.118.48.112  51753  10.153.20.27     443   6   RAGG30       RAGG50.4000  1     

所以你以为路由器每次都会全量的查一遍路由表?不,FIB和FFT可以更快速的确定IP报文转发方向。

3、路由器的IP上一条保持技术

在H3C的设备中,我们找到了IP上一条保持技术的配置说明。其他厂家的设备,读者感兴趣也可以找找看。

如下图所示,外网服务器向内网服务器发起业务请求,请求报文通过ISP1到达Device设备。

用户希望相同会话或连接的正向流量与反向流量保持相同的转发路径,即反向报文可以通过最初接收请求报文的Interface A接口转发出去。

但是在正常的转发过程中,Device设备会选择最佳链路进行报文的转发,这样就无法保证正反向流量路径一致。

这种情况下,用户可以在接收正向流量的Interface A接口上开启保持上一跳功能。

开启保持上一跳功能后,当该接口接收到正向流量的第一个IP报文,在高速缓存中会记录相应的流量特征以及上一跳信息,反向流量报文到达设备上进行转发时可以直接通过该上一跳信息指导报文进行转发。保证了从对端到本端的正向流量和本端到对端的反向流量走的是相同的路径,从而保证同一会话的流量能够进行相同的业务处理。
在这里插入图片描述
保持上一跳功能依赖于快速转发表项的建立,如果上一跳的MAC地址发生变化,对应的快速转发表项需要重建才能使保持上一跳功能正常工作。

说了这么多,原理搞明白之后,命令其实很简单,在所有的公网接口上使能last-hop hold特性即可。

#
interface GigabitEthernet1/0/1
    ip last-hop hold
#

四、GRE Tunnel上的上一跳保持

话接上文,现在深圳的路由器回包问题解决了。但是对于从北京过来的请求,回包要穿越MPLS网络,那么如何让目的IP是公网的IP报文,穿越MPLS网络呢?

聪明的读者一定已经想到了,起隧道呀,万能的GRE Tunnel技术呀。

但是!但是!但是!
GRE隧道上不支持前文说到的IP上一跳保持技术!原因我们慢慢分析。

1、GRE Tunnel的FFT表项问题

首先,命令是敲不上的。H3C官方也没有给出说明。所以我尝试从GRE的原理来尝试解释一下,从现在开始,大家有任何问题,欢迎在评论区一起讨论。

GRE隧道“属于”主机,也就是说,我们所说的“隧道”,逻辑上说,是A主机和B主机间的一个协议,是主机的,不是接口的,不是以IP路由为逻辑主体的。

对于IP路由表中,下一跳是GRE隧道接口的,实际应上报到CPU的GRE模块进行封装。同时我们可以想象到一个有趣的问题,IP报文在经由GRE隧道转发的时候,GRE隧道接口的IP地址其实一点用都没有。GRE隧道的接口地址在路由器中的性质,类似于环回口,是一个挂载CPU上的黑洞路由地址。

那么快速快速转发表能不能利用CPU上的地址作为下一跳生成快转表项呢?其实从查看FFT表信息来看,确实生成了。但是与物理接口生成的表项不同。

我们找了好多方法,最终在FFT表上发现了对于出接口是Tunnel接口这种长江下,发现了些许端倪。

对于DNAT流量,到服务器方向出接口是物理接口的,FFT在处理的时候会正确识别到目的IP地址为服务器内网IP。但如果向北京这种使用Tunnel隧道作为出接口的情况,FFT没有识别到正确的目的IP,识别出的是DNAT之前的公网IP。

这个示例虽然方向是Tunnel作为出接口时的情况(本案例中,我们需要Tunnel入方向的FFT表项支持上一跳保持),但是侧面印证了一个猜想。就是GRE隧道的流量处理没有下放到FIB。实际是通过虚拟在CPU上的接口+物理接口的FIB表转发。但是,为了维护起来方便,FFT和FIB表中会出现Tunnel接口的表项,只不过并没有以此作为真实的生效出接口。

没有正确的FTT表项支持,IP上一条保持功能可能就无法正常运行。

当然,说了这么多,总结一点就是,H3C的研发太懒!

<BJ-08F-MDF-Core-FW>dis ip fast-forwarding cache | in Tun1
Source IP       SPort  Destination IP   DPort Pro Input_If     Output_If    Flg
10.153.20.27    443   218.17.158.232    22998 6   Tun1         GE1/0/1      1    
10.153.20.27    443   218.17.158.232    21192 6   Tun1         GE1/0/1      1    
218.17.158.232  21554 214.187.250.99    443   6   GE1/0/1      Tun1         1    
27.17.70.0      8229  214.187.250.99    443   6   GE1/0/1      Tun1         1    
218.17.158.232  22998 214.187.250.99    443   6   GE1/0/1      Tun1         1    
218.17.158.232  21197 214.187.250.99    443   6   GE1/0/1      Tun1         1    
218.17.158.232  21192 214.187.250.99    443   6   GE1/0/1      Tun1         1    


<SZ-10F-MDF-Core-FW>display ip fast-forwarding cache
Total number of fast-forwarding entries: 127446
Source IP       SPort  Destination IP   DPort Pro Input_If     Output_If    Flg
103.118.48.112  51754  10.153.20.27     443   6   RAGG10       RAGG50.4000  0    
112.95.224.94   55190  10.153.20.27     443   6   RAGG10       RAGG50.4000  0    
112.82.89.37    22752  10.153.20.27     443   6   RAGG10       RAGG50.4000  1    
14.127.83.81    6248   10.153.20.27     443   6   RAGG60.4002  RAGG50.4000  0       
117.136.33.185  29324  10.153.20.27     443   6   RAGG40       RAGG50.4000  1    
112.82.89.37    24701  10.153.20.27     443   6   RAGG60.4003  RAGG50.4000  0    
112.82.89.37    25194  10.153.20.27     443   6   RAGG10       RAGG50.4000  1    
14.154.29.33    24511  10.153.20.27     443   6   RAGG60.4002  RAGG50.4000  0    
113.116.23.122  59620  10.153.20.27     443   6   RAGG30       RAGG50.4000  0    
103.118.48.112  51753  10.153.20.27     443   6   RAGG30       RAGG50.4000  1    

2、解决方案

既然,GRE Tunnel暂时无法直接支持IP上一跳保持,那么有没有其他办法绕开这个限制呢?

只要思想不滑坡,办法总比困难多!

逻辑接口不支持,那么我们就给他换成物理接口,怎么做?

加一台设备不就完了!

老夫搬出了一台新路由器。这个路由器不需要高端的功能,只需要支持一个功能就可以,那就是PBR,策略路由。

我们让这台PBR转发路由器与深圳的核心路由器之间建立多个子接口。每个子接口代表一个pop节点。通过PBR转发路由器与各个pop节点建立GRE Tunnel。

然后,在PBR转发路由器上,通过PBR 1:1绑定 GRE Tunnel和子接口。通过A站点的Tunnel收到的流量,策略路由转发到A站点对应的子接口。从A站点对应的子接口收到流量,策略路由转发到GRE Tunnel。

然后在深圳的核心路由器上,基于物理接口配置IP上一条保持功能,则就没有任何问题了。
在这里插入图片描述

3、配置案例

这台PBR转发路由器,不限品牌不限型号。但是为了让这篇文章看起来更有B格一些,我从库房里找了一台思科的路由器来配置route-map。下面摘取一下核心路由器和PBR转发路由器上的关键配置

H3C 核心路由器配置:

<SZ-10F-MDF-Core-FW>dis cu int rou 60.4002
#
interface Route-Aggregation60.4002
 description Beijing-Office-Server-Access-Traffic-IN
 ip address 10.0.9.245 255.255.255.252
 ip last-hop hold
 vlan-type dot1q vid 4002
#北京pop节点对应的子接口,封装802.1q vid 4002

<SZ-10F-MDF-Core-FW>dis cu int rou 60.4002
#
interface Route-Aggregation60.4003
 description Jakarta-Office-Server-Access-Traffic-IN
 ip address 10.0.9.249 255.255.255.252
 ip last-hop hold
 vlan-type dot1q vid 4003
#雅加达pop节点对应的子接口,封装802.1q vid 4003

Cisco PBR转发路由器配置:

Cisco_PBR_Transfer_node_1#show ip int brief 
Interface                  IP-Address      OK? Method Status                Protocol

GigabitEthernet0/1.10      10.0.0.20       YES manual up                    up      
GigabitEthernet0/1.4002    10.0.9.246      YES manual up                    up      
GigabitEthernet0/1.4003    10.0.9.250      YES manual up                    up      


interface GigabitEthernet0/1.4002
 description Beijing_Traffic_AS_65002
 encapsulation dot1Q 4002
 ip address 10.0.9.246 255.255.255.252
 ip tcp adjust-mss 1360
 ip policy route-map Beijing_Office_Server_OUT
end
#北京pop节点对应的子接口,封装802.1q vid 4002

interface GigabitEthernet0/1.4003
 description Jakarta_Traffic_AS_65003
 encapsulation dot1Q 4003
 ip address 10.0.9.250 255.255.255.252
 ip tcp adjust-mss 1360
 ip policy route-map Jakarta_Office_Server_OUT
end
#雅加达pop节点对应的子接口,封装802.1q vid 4003

interface Tunnel65002
 description Beijing_Office_FW_GW
 ip address 192.168.251.246 255.255.255.252
 ip policy route-map Beijing_Office_Server_IN
 keepalive 10 3
 tunnel source Loopback1
 tunnel destination 10.2.0.1
end
#北京pop节点对应的GRE Tunnel接口
interface Tunnel65003
 description Jakarta_Office_FW_GW
 ip address 192.168.251.250 255.255.255.252
 ip policy route-map Jakarta_Office_Server_IN
 keepalive 10 3
 tunnel source Loopback1
 tunnel destination 10.3.0.1
end
#雅加达pop节点对应的GRE Tunnel接口

Cisco_PBR_Transfer_node_1#show route-map
route-map Beijing_Office_Server_IN, permit, sequence 10
  Match clauses:
  Set clauses:
    ip next-hop 10.0.9.245
  Policy routing matches: 1560720 packets, 282322329 bytes
route-map Beijing_Office_Server_OUT, permit, sequence 10
  Match clauses:
  Set clauses:
    ip next-hop 192.168.251.245
  Policy routing matches: 1847387 packets, 1201474231 bytes

route-map Jakarta_Office_Server_IN, permit, sequence 10
  Match clauses:
  Set clauses:
    ip next-hop 10.0.9.249
  Policy routing matches: 117412822 packets, 58195285636 bytes
route-map Jakarta_Office_Server_OUT, permit, sequence 10
  Match clauses:
  Set clauses:
    ip next-hop 192.168.251.249
  Policy routing matches: 114712282 packets, 298536221475 bytes
#route-map状态

route-map Beijing_Office_Server_IN permit 10
 set ip next-hop 10.0.9.245
!
route-map Beijing_Office_Server_OUT permit 10
 set ip next-hop 192.168.251.245

route-map Jakarta_Office_Server_IN permit 10
 set ip next-hop 10.0.9.249
!
route-map Jakarta_Office_Server_OUT permit 10
 set ip next-hop 192.168.251.249
#route-map配置,简单粗暴强制下一跳

由于PBR路由器上1:1绑定了对应的GRE Tunnel和子接口之间的转发,因此这台设备不需要学习IP路由表。只需要保持一个管理流量的缺省路由即可。

五、总结

至此,算是搞定了。

本案例说来繁琐,但是挺有趣的。这是一个在特定场景下诞生的解决方案,如果不需要穿越MPLS,如果不是强求保留真实源IP,这个问题都会简单很多。

但是我们网工,要的不就是这种挑战各种奇葩需求之后,得到一个最终解决方案的快感么

往期回顾:
【逗老师带你学IT】阿里云监控报警回调+转发企业微信+转发SnmpTrap+PRTG
【逗老师带你学IT】PRTG监控通过Python+TCP Modbus获取温湿度传感器数据
【逗老师带你学IT】HUAWEI华为防火墙自动化运维Python ssh管理网络设备
【逗老师带你学IT】PRTG获取HUAWEI FusionServer iBMC传感器状态
【逗老师带你学IT】PRTG自定义脚本ssh登录网络设备获负载均衡链路状态
【逗老师带你学IT】Django+IIS+Python构建微软AD域控API管理中心
【逗老师带你学IT】通过企业微信推送AD域密码即将到期提醒
【逗老师带你学IT】AD域控 Dsquery 查询命令实例汇总
【逗老师带你学IT】Google Admin服务账号+API管理G suit内所有网域用户
【逗老师带你学IT】PRTG监控系统通过企业微信推送图文混排告警消息
【逗老师带你学IT】PRTG HTTP API获取指定传感器流量图表图片
【逗老师带你学IT】PRTG监控系统合并多个传感器通道数据
【逗老师带你学IT】PRTG监控系统通过企业微信推送告警消息
【逗老师带你学IT】PRTG监控系统配合树莓派采集企业内部无线网络质量
【逗老师带你学IT】vMware ESXi 6.7合并第三方硬件驱动
【逗老师带你学IT】Kiwi Syslog Server安装和配置教程
【逗老师带你学IT】Kiwi Syslog Web Access与Active Directory集成认证
【逗老师带你学IT】vMware ESXi 6.7合并第三方硬件驱动
【逗老师带你学IT】Windows Server Network Policy Service(NPS)记账与审计
【逗老师带你学IT】Windows Server NPS服务构建基于AD域控的radius认证
【逗老师带你学IT】AD域控和freeradius集成认证环境,PAP,MSCHAPV2
【逗老师带你学IT】深信服SSL远程接入与深信服行为审计同步登陆用户信息

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逗老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值