美文网首页
LVS VS/DR实验

LVS VS/DR实验

作者: li_zw | 来源:发表于2018-06-22 14:22 被阅读0次

    VS/DR模型的原理

    (1)当负载均衡器(Director)收到访问VIP的报文的时候,它首先会把2层的数据帧拆开,得到里面3层的数据,发现目标IP是自己的,然后发往INPUT链上,由于INPUT上我们已经配置了LVS集群服务,并且是DR模式,所以LVS会重新封装一个2层帧,源MAC地址则是出栈的网卡MAC,目的MAC则是由调度算法得出来的某RIP的MAC地址,但是原包的源IP和目的IP是不会更改的,最后发回给交换机
    (2)交换机收到数据帧后,根据目的MAC把数据帧发到对应的RS上,当RS收到数据帧后,拆开2层帧,查看3层内容,目的IP是VIP,在此模式下,VIP应该已经在RS上配置,所以收下来。
    (3)当RS收到请求报文后,由于目的IP是VIP,而自己协议栈中是有此IP,所以发往到用户空间的HTTP程序;HTTP响应报文则直接发送到RS的网关上面,此时响应报文的源IP应该是VIP,目的IP是CIP。源MAC则是出栈的网卡MAC,目的MAC则是网关。最后客户端成功收到报文。

    以上,有几个问题需要思考和注意。
    1.DIP和RIP之间通信不是通过IP网络层,只是通过2层数据链路层的MAC地址通信,所以DIP跟RIP必须是同一物理网络,即连在同一交换机上。

    2.由于响应报文的源IP必须是VIP,所以在RS上需要配置一个VIP。
    通常我们在RS的一个回环接口上配置一个VIP,然后再配置一条静态路由,把目的为VIP的数据,都通过lo接口传入,这样在回包时,响应报文的源IP就为VIP了。

    3.如果RS只有一个网卡,数据流入流出都需要经过RIP,所以RIP跟网关必须在同一子网,这样的话,那么VIP似乎都要跟RIP在同一子网囖?
    ~是的,如果RS只有一个出口,那么在这个情况下,VIP跟RIP都需要在同一子网中,如果在RS上配置了多张网卡,数据流出能经由其他网卡,那RIP和VIP就可以不用处于同一子网中。

    4.既然后端的RS都配置了VIP,需要更多的是考虑ARP问题。

    • 一个主机加入了网络后,默认会向所有接口通告自己的IP和MAC地址,此时我们应该禁止通告VIP地址和MAC地址
    • 当网关在收到目的地址为VIP的数据包时,会发送ARP请求,请求VIP的MAC地址是什么,此时,我们应该只允许作为调度器的服务器去响应这个报文,RS不能响应此报文。

    一个linux主机在加入网络后,默认会通告自己所有的IP地址给所有接口,但我们应该禁止它通告VIP给任何人。还有就是,在发起ARP请求时候,源IP不可以为VIP。可以通过内核参数:arp_announce来控制。

    arp_announce简介:

    arp_announce它的作用是控制系统对外发送arp请求时,如何选择请求包的源IP

    arp_announce的参数

    0:默认值,允许使用任意网卡上的IP地址作为arp请求的源IP,很可能会使用流出接口的IP地址和MAC地址。
    1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。
    2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。

    arp_announce在DR模式下的作用:

    每台服务器或交换机等都有一张2层转发表,称为ARP表,该表是保存这IP与MAC地址之间的对应关系。当收到一个ARP请求时,会缓存该请求的源IP和源MAC,当收到一个已知IP地址(arp表中已有记录的地址)的arp请求,则会根据arp请求中的源MAC刷新自己的arp表。
    如果arp_announce=0,也是默认值,则网卡在发送arp请求时,可能选择的源IP地址并不是该网卡自身的IP地址,如果在RS设置了arp_announce=0意味着发送ARP请求时,源IP可能会是VIP,这样会带来问题的。所以一般在DR模式下,arp_announce设置为2,这样,在发送ARP或通告ARP时候,源IP和源MAC肯定是出栈的网卡地址。而不会是VIP

    以上参数,只是解决了发送的APR请求时的源IP和源MAC问题,但如果RS收到了对VIP的ARP的请求会作回应的,所以我们应该禁止此情况发生,可以使用内核参数:arp_ignore来作限制:

    arp_ignore简介:

    参数的作用是控制系统在收到外部的arp请求时,是否要返回arp响应
    参数常用的取值
    0:默认值,表示可使用本地任意接口上配置的任意地址进行响应
    1:仅在请求的目标IP配置在本地主机的接收到请求报文接口上时,才给予响应;

    arp_ignore在DR模式下的作用:

    每个真实服务器节点都要在环回网卡上绑定虚拟服务IP。这时候,如果客户端对于虚拟服务IP的arp请求广播到了各个真实服务器节点,如果arp_ignore参数配置为0,则各个真实服务器节点都会响应该arp请求,
    此时负载均衡可能失去控制。通常我们把arp_ignore设置为1,限制只请求RIP网卡的MAC地址才予以响应。

    实验1:VIP/DIP/RIP处于同一子网的场景

    实验拓扑:

    LVS DR.png-31.2kBLVS DR.png-31.2kB
    路由器IP设置:
    [root@route ~]# ip a s 
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
       
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc =
        inet 192.168.30.98/24 brd 192.168.30.255 scope global =
        
    3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc =
        inet 172.16.1.1/24 brd 172.16.1.255 scope global =
        
    
        
    调度器IP设置://注意,VIP配置在ens的子接口上
    [root@director ~]# ip a s 
    ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.16.1.98  netmask 255.255.255.0  broadcast 172.16.1.255
    
    
    ens33:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.16.1.99  netmask 255.255.255.255  broadcast 172.16.1.99
            ether 00:0c:29:fb:84:fb  txqueuelen 1000  (Ethernet)
    
    
    
    
    RS1服务器IP:
    [root@rs1 ~]# ip a s 
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state 
        inet 127.0.0.1/8 scope host lo
         
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 172.16.1.11/24 brd 172.16.1.255 scope global 
        
    RS2服务器IP:
    [root@rs2 ~]# ip a s 
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        inet 127.0.0.1/8 scope host lo
         
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 172.16.1.12/24 brd 172.16.1.255 scope global 
    
    
    
    

    在为各RS增加IP之前,需要对2各内核参数对ARP进行修改
    也就是arp_announce和arp_ignore

    对个RS的2个参数进行设置:
    一般来讲,对这2类参数很多情况下用脚本实现,即通用又方便管理,而且还原也很方便。

    #/bin/bash
    #
    #
    case $1 in
    #SET 
    start)
            echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
            echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
            echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
            echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
            ;;
    #UNSET
    stop)
            echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
            echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
            echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
            echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
            ;;
    *)
            echo "Usage $(basename $0 ) start|stop"
            exit 1
    esac
    

    配置好各RS参数后,接下来在RS的回环接口上增加一个VIP

     ~]# ifconfig lo:0 172.16.1.99 netmask 255.255.255.255 up
    
    lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 172.16.1.99  netmask 255.255.255.255
            loop  txqueuelen 1000  (Local Loopback)
    
    2台RS都配置VIP
    

    为了保证响应报文的的源IP是VIP,所以数据入栈时,应该经由lo接口入栈,那数据出去会从lo接口出栈,由此,配置在RS上配置一条静态路由,所有访问VIP的数据都经由lo接口。

    两台RS都配置:

    ~]# route add -host 172.16.1.99 dev lo:0
    
    

    接下来,就可以在调度器上配置规则了:

    [root@director ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  172.16.1.99:80 rr
      -> 172.16.1.11:80               Route   1      0          0         
      -> 172.16.1.12:80               Route   1      0          0   
    

    配置客户端,把网关设置成充当路由器的Linux
    客户端IP

    [root@localhost ~]# ip a s
    
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 192.168.30.148/24 brd 192.168.30.255 scope global 
        
    路由表:
    [root@localhost ~]# ip route s
    default via 192.168.30.98 dev ens33 proto static metric 20100 
    192.168.30.0/24 dev ens33 proto kernel scope link src 192.168.30.148 metric 100 
    
    
    [root@localhost ~]# for i in {1..5};do curl http://172.16.1.99/test.html;done
    This Page form rs2
    This Page form rs1
    This Page form rs2
    This Page form rs1
    This Page form rs2
    

    实验2:VIP和DIP/RIP不在同一网段的实验。

    拓扑图

    VIP与DIP-RIP不在同一网段实验.png-45.2kBVIP与DIP-RIP不在同一网段实验.png-45.2kB

    虚拟机网络环境

    image_1cgh6e89p739jo8ba1jdct2q43.png-24.9kBimage_1cgh6e89p739jo8ba1jdct2q43.png-24.9kB

    说明:按照拓扑图,各主机的网卡连接的网络情况如下:

    1. 充当路由器的Linux主机:
      网卡1:NAT模式,用于模拟与外网通信(地址:192.168.30.98)
      网卡2:连接到VMnet2,用于与VIP通信(地址:172.16.1.1)
      网卡3:连接到VMnet4,用于RS的网关(地址:10.1.1.1)

    2. 调度器(Director)
      网卡1:连接到VMnet2,配置VIP地址(地址:172.16.1.99)
      网卡2:连接到VMnet3,用于与RS通信(地址:192.168.10.99)

    3. RS1
      网卡1:连接到VMnet3,用于与调度器通信(地址:192.168.10.11)
      网卡2:连接到VMnet4,与网关通信(地址:10.1.1.11)
      按照拓扑图配置好全部虚拟机的IP

    4. RS2
      网卡1:连接到VMnet3,用于与调度器通信(地址:192.168.10.12)
      网卡2:连接到VMnet4,与网关通信(地址:10.1.1.12)

    按照拓扑图配置好全部虚拟机的IP

    路由器的IP配置
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state 
        inet 127.0.0.1/8 scope host lo
          
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 192.168.30.98/24 brd 192.168.30.255 scope global 
        
    3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 172.16.1.1/24 brd 172.16.1.255 scope global 
        
    4: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 10.1.1.1/24 brd 10.1.1.255 scope global 
           
    路由表:
    [root@route ~]# ip route s 
    default via 192.168.30.2 dev ens33 proto static metric 103 
    10.1.1.0/24 dev ens37 proto kernel scope link src 10.1.1.1 metric 102 
    172.16.1.0/24 dev ens36 proto kernel scope link src 172.16.1.1 metric 101 
    192.168.30.0/24 dev ens33 proto kernel scope link src 192.168.30.98 metric 103
           
    -------------------------------------------------------------
    调度器的IP设置:
    [root@director ~]# ip a s 
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state 
        inet 127.0.0.1/8 scope host lo
         
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 172.16.1.99/25 brd 172.16.1.127 scope global 
        
    3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 192.168.10.99/24 brd 192.168.10.255 scope global 
        
    路由表:
    [root@director ~]# ip route s 
    default via 172.16.1.1 dev ens33 proto static metric 100 
    172.16.1.0/25 dev ens33 proto kernel scope link src 172.16.1.99 metric 100 
    192.168.10.0/24 dev ens36 proto kernel scope link src 192.168.10.99 metric 101 
    
    -------------------------------------------------------------
    
    RS1的IP设置:
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state 
        inet 127.0.0.1/8 scope host lo
         
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 192.168.10.11/24 brd 192.168.10.255 scope global 
        
    3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 10.1.1.11/24 brd 10.1.1.255 scope global 
        
    路由表:
    [root@rs1 ~]# ip route s 
    default via 10.1.1.1 dev ens36 proto static metric 100 
    10.1.1.0/24 dev ens36 proto kernel scope link src 10.1.1.11 metric 100 
    192.168.10.0/24 dev ens33 proto kernel scope link src 192.168.10.11 metric 101 
    
    -------------------------------------------------------------
    
    RS2的IP设置:
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state 
        inet 127.0.0.1/8 scope host lo
          
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 192.168.10.12/24 brd 192.168.10.255 scope global  
        
    3: ens36: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
        inet 10.1.1.12/24 brd 10.1.1.255 scope global 
    
    路由表:
    [root@rs2 ~]# ip route s 
    default via 10.1.1.1 dev ens36 proto static metric 100 
    10.1.1.0/24 dev ens36 proto kernel scope link src 10.1.1.12 metric 100 
    192.168.10.0/24 dev ens33 proto kernel scope link src 192.168.10.12 metric 101 
    
    

    在路由器上打开IP转发功能

    充当路由器的Linux打开IP转发功能
    [root@route ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

    配置SNAT

    此外,在这个拓扑图中,充当路由器的linux主机只有一个连接外网的出口,就是NAT的那块网卡,所以对于调度器和RS主机的网关数据的流出,我使用iptables的SNAT转换源IP使数据流出。

    对于172.16.1.0和10.1.1.0 我使用SNAT转换。
    [root@route ~]# iptables -t nat -nvL
    ...
    Chain POSTROUTING (policy ACCEPT 27 packets, 2043 bytes) 
     pkts bytes target     prot opt in     out     source               destination         
      138  9918 MASQUERADE  all  --  *      ens33   172.16.1.0/24        0.0.0.0/0           
       65  4821 MASQUERADE  all  --  *      ens33   10.1.1.0/24          0.0.0.0/0  
     
    

    限制ARP

    接下来,配置2台RS的内核参数,限制ARP请求。
    为了方便管理,我使用脚本来实现:

    [root@rs1 ~]# ./set_arp.sh start
    [root@rs2 ~]# ./set_arp.sh start
    

    脚本内容:

    #/bin/bash
    #
    case $1 in
    start)
            echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
            echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
            echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
            echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
            ;;
    stop)
            echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
            echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
            echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
            echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
            ;;
    *)
            echo "Usage $(basename $0) start|stop"
            exit 1
            ;;
    esac
    
    

    在RS上配置VIP

    在各RS上的lo:0接口上配置VIP

    [root@rs2 ~]# ifconfig lo:0 172.16.1.99 up
    [root@rs1 ~]# ifconfig lo:0 172.16.1.99 up
    
    

    在RS上配置静态路由

    为了让响应包的源IP设置为VIP,所以在各RS上配置一条静态路由。

    [root@rs1 ~]# route add -host 172.16.1.99 dev lo:0
    [root@rs2 ~]# route add -host 172.16.1.99 dev lo:0
    
    在RS1上查看路由表:
    [root@rs1 ~]# ip route s 
    default via 10.1.1.1 dev ens36 proto static metric 100 
    10.1.1.0/24 dev ens36 proto kernel scope link src 10.1.1.11 metric 100 
    172.16.1.99 dev lo scope link src 172.16.1.99   //转发到lo:0上处理
    192.168.10.0/24 dev ens33 proto kernel scope link src 192.168.10.11 metric 101 
    
    RS2上也一样的,所以就不贴了
    

    配置HTTP服务

    接下来,配置好NGINX服务,新建测试页,为了测试方便,所以2台RS都写不同的内容,这样看到的效果会更明显。

    [root@rs1 ~]# yum install nginx 
    [root@rs1 ~]# vim /usr/share/nginx/html/test.html 
    This Page from RS1!
    xxx
    
    [root@rs1 ~]# systemctl start nginx 
    
    RS2上也是一样的操作 ,所以我不贴了
    
    
    

    测试HTTP服务

    直接使用RIP访问无问题:


    image_1cggiof114jj17rm51lm55ejl9.png-22.9kBimage_1cggiof114jj17rm51lm55ejl9.png-22.9kB image_1cggj44bh1kadan15nmq3v44816.png-22.2kBimage_1cggj44bh1kadan15nmq3v44816.png-22.2kB

    在调度器上配置调度规则

    接下来,配置调度器规则。

    [root@director ~]# ipvsadm -A -t 172.16.1.99:80 -s rr 
    [root@director ~]# ipvsadm -a -t 172.16.1.99:80 -r 192.168.10.11 -g
    [root@director ~]# ipvsadm -a -t 172.16.1.99:80 -r 192.168.10.12 -g
    
    查看规则:
    [root@director ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  172.16.1.99:80 rr
      -> 192.168.10.11:80             Route   1      0          0         
      -> 192.168.10.12:80             Route   1      0          0   
    

    至于,配置完成,接下来还有一个非常关键的问题。
    以下是借鉴骏马金龙博客(http://www.cnblogs.com/f-ck-need-u/p/8472744.html)的文章

    反向追踪

    如果按以上配置的话,按逻辑上,是应该可以成功负载的,但是实际上,是不能成功访问到的,因为涉及到了反向路径过滤的问题。
    反向路径过滤的问题
    linux内核有一个反向路径过滤的功能参数,叫rp_filter,rp_filter参数有三个值,0、1、2,Linux上默认为1。
    0:不开启反向追踪
    1:严格检验 (Linux默认是1)
    2:松散校验

    按照默认值会有2个问题发生:

    问题一
    拓扑图种,我的Linux充当了路由器,并且默认rp_filter=1,响应数据包从ens37网卡收到,但是根据我的路由表,该数据包出去的网卡却是ens33,这时,Linux认为这不是最佳路径,所以会把数据包丢弃。

    如果设置rp_filter=2,只要Linux反向检查时能和VIP能互相通信就能满足检查条件,即使尽管检查的接口和接收RS数据包的接口不同也无所谓。换句话说,当设置为该值时,无论RIP、VIP是否同网段,数据包都会保留并转发给Client;

    如果设置rp_filter=0,则完全不检查源地址,直接转发。

    以上是在Linux作为Route的设置。

    问题二:
    在RS上也需要设置。
    在RS上,收到对VIP的请求包需要转发到lo接口上,最后由ens36发出。
    RIP的网卡收到后,会严格反向追踪检查,检查源地址的发出接口是不是和接受的接口是同一网卡,这样,由于请求包由ens33收到,但是发出是由ens36发出,Linux认为这是不是最佳路径,所以丢弃。

    以上分析,需要对充当Route和RS这几台服务器修改一下rp_filter,一般该为2即可。

    路由器上设置
    [root@route ~]# echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter
    
    RS上设置
    [root@rs1 conf]# echo 2 >  /proc/sys/net/ipv4/conf/lo/rp_filter
    [root@rs2 conf]# echo 2 >  /proc/sys/net/ipv4/conf/lo/rp_filter
    

    测试

    在客户端上测试:

    [root@localhost ~]# for i in {1..5};do curl http://172.16.1.99/test.html;done
    This Page from RS2!
    This Page from RS1!
    This Page from RS2!
    This Page from RS1!
    This Page from RS2!
    

    已经能正常调度。

    抓包分析

    在路由器的ens33抓包

    在拓扑图中,路由器的ens33是数据的必经之路,TCP3次握手,请求报文和响应报文都应该能捕捉到。如图:


    image_1cggq388k354v301d5q19h29m21j.png-103kBimage_1cggq388k354v301d5q19h29m21j.png-103kB

    红色方框:3次握手过程
    蓝色方框:客户端的请求报文以及服务端的ACK确认报文
    橙色方框:服务端的响应报文以及客户端的ACK确认报文
    紫色方框:4次挥手过程,但实际上只有3次报文交互。

    调度器的抓包情况

    在调度器上,一定只能捕捉到客户端发给服务端的包,服务端的响应包不可能在调度器上被抓到的。


    image_1cggqdporonf1q3r1q3u1o4618vo2g.png-66.7kBimage_1cggqdporonf1q3r1q3u1o4618vo2g.png-66.7kB

    红色方框:TCP3次握手的报文,这里只有2个,有一个包是服务端响应给客户端的,所以在调度器是捉不到的
    蓝色方框:客户端的请求报文。
    橙色方框:服务端发给客户端后,客户端发送ack确认报文
    紫色方框:四次挥手过程。客户端发了2个包给服务端,一个是fin断开包,还有一个是确认包,中间的包由于不经由调度器,所以不能捉到。

    最后在路由器的ens37(RS的网关上的数据包)

    image_1cggqptpfeu7142c1m8p136ttot2t.png-52.6kBimage_1cggqptpfeu7142c1m8p136ttot2t.png-52.6kB

    红色方框:服务端发给客户端的TCP握手确认包
    蓝色方框:客户端发送请求报文给服务端,服务端发回ACK确认报文
    橙色方框:客户端发送的请求报文
    紫色方框:挥手包。

    总结
    从抓包情况分析,跟LVS/DR原理实现一样,数据包的确通过调度器转发给RS服务器,RS服务器响应报文也不经由调度器,这样,调度器的吞吐效率大幅提升。

    相关文章

      网友评论

          本文标题:LVS VS/DR实验

          本文链接:https://www.haomeiwen.com/subject/nbykyftx.html