[NSX] LB traffic fails intermittently (2)
https://haewon83.tistory.com/221 에서 테스트를 위한 환경을 구축했습니다.
이제 Client에서 LB에 연결한 후 어떤 조건에서 Connection이 끊기는 상황이 발생할 수 있는지 확인해보겠습니다.
1. Nginx 파일 다운로드 구성
우선 Back-end Server로 구성해놨던, Nginx를 통해 파일을 다운로드 할 수 있도록 아래 설정을 추가하고 Nginx를 재시작 합니다.
※ 테스트를 위해서 사전에 selinux는 비활성화 하시길 권고드립니다.
location /downloads/ { >>>>>>>>>>>>>>>>>>>>>> 웹브라우저에서 접근 시 사용할 경로 root /home/jhaewon/; >>>>>>>>>>>>>>>>>>>>>> 실제 파일이 위치하는 경로의 상위 디렉토리, 즉 위에 기재한 /downloads/와 합쳐서 실제 디렉토리는 /home/jhaewon/downloads autoindex on; charset utf-8; } |
위 설정을 하고 나면 제가 내부에서 테스트 한 Nginx 서버의 Default Configuration은 다음과 같습니다.
[root@localhost var]# cat /etc/nginx/nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 4096; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80; listen [::]:80; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location /downloads/ { root /home/jhaewon/; autoindex on; charset utf-8; } error_page 404 /404.html; location = /404.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } } |
위 설정을 완료하고 나면 /home/jhaewon/downloads 폴더 하위에 있는 파일들이 다음과 같이 출력됩니다.
[root@localhost var]# ls -al /home/jhaewon/downloads/ total 115968 drwxr-xr-x. 2 jhaewon nginx 87 May 29 11:48 . drwxr-xr-x. 3 jhaewon jhaewon 100 May 29 11:34 .. -rw-rw-r--. 1 jhaewon jhaewon 117110832 May 29 11:49 ChromeStandaloneSetup64.exe -rw-rw-r--. 1 jhaewon jhaewon 1632728 May 29 11:46 MicrosoftEdgeSetup.exe -rw-rw-r--. 1 jhaewon nginx 5 May 29 11:34 text.txt |
Client PC에서 curl 명령어를 통해 정상적으로 다운로드 되는지 확인합니다.
C:\>curl.exe "http://172.31.1.51/downloads/ChromeStandaloneSetup64.exe" -o ChromeStandaloneSetup64.exe % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 111M 100 111M 0 0 59.9M 0 0:00:01 0:00:01 --:--:-- 59.9M |
이제 문제를 재현해보겠습니다.
2. 아래 2개의 Rule을 LB T1에 있는 Service Interface에 Firewall Rule 등록
ANY-ANY DROP rule
from ANY to HTTP VIP (172.31.4.70) to ALLOW rule
3. Client에서 curl command를 통해 LB VIP에 연결하여 파일 다운로드
연결 시간을 오래 가져가기 위해서 약 3GB 정도의 파일을 Back-end Server에 업로드 해놓고 진행
C:\>curl.exe "http://172.31.5.70/downloads/test.txt" -o test.txt |
4. 파일 다운로드를 시작하면 LB T1에 생성한 Service Interface의 Firewall Connection 확인
Connection 중 SNAT IP Address(172.31.3.254) → Back-end Server IP Address(172.31.1.51)가 확인되며, Firewall Rule ID가 0으로 표시되는데, 이는 Firewall Rule에는 Match 되지 않고 그 뒤에 있는 Rule ID 3인 LB Rule에만 Match 된다는 의미
edge-node-01> get firewall 93676e05-2ca1-45f5-b84f-0bd9a704307c connection Thu May 30 2024 UTC 10:30:58.444 Connection count: 2 0x0400b5fd3800000b: 192.168.1.2:64446 -> 172.31.4.70:80 dir in protocol tcp state ESTABLISHED:ESTABLISHED fn 1022:0 0x0800b5fd38000011: 172.31.3.254:4102 -> 172.31.1.51:80 (172.31.3.254:4102) dir out protocol tcp state ESTABLISHED:ESTABLISHED fn 0:3 |
5. 그 사이 전혀 상관없는 Firewall Rule을 LB T1의 Service Interface에 생성
Source IP는 3.1.1.10, Destination IP는 4.1.1.10
6. 그 후 추가한 Firwall Rule을 다음과 같이 변경
Source IP는 192.168.1.2(Client PC), Destination IP는 124.124.124.124(사용하지 않는 IP)
7. Service Interface의 Firewall Connection을 다시 확인
다음과 같이 Firewall Rule ID가 0에서 1021로 변경되어 있고, "->"이 "!->" 로 변경되어 있음
edge-node-01> get firewall 93676e05-2ca1-45f5-b84f-0bd9a704307c connection Thu May 30 2024 UTC 10:32:40.551 Connection count: 2 0x0400b5fd3800000b: 192.168.1.2:64446 -> 172.31.4.70:80 dir in protocol tcp state ESTABLISHED:ESTABLISHED fn 1022:0 0x0800b5fd38000011: 172.31.3.254:4102 !-> 172.31.1.51:80 (172.31.3.254:4102) dir out protocol tcp state ESTABLISHED:ESTABLISHED fn 1021:3 |
Firewall Rule ID 1021은 처음에 생성했던 Any-Any Drop Rule로 확인
edge-node-01> get firewall 93676e05-2ca1-45f5-b84f-0bd9a704307c ruleset rules Thu May 30 2024 UTC 10:32:49.883 DNAT rule count: 1 Rule ID : 7 Rule : in protocol tcp natpass from any to ip 172.31.4.70 port 80 lb lbtype L7 lboptions b2551414-e460-4de4-a5c1-f4c47e9a93e8 7a5ca4e7-d5d2-4aaf-900e-31ba9be9a5fa tag 'loadbalancer' SNAT rule count: 1 Rule ID : 3 Rule : out protocol tcp natpass from any to ip 172.31.1.51 port 80 lb lbtype L7 lboptions b2551414-e460-4de4-a5c1-f4c47e9a93e8 fdd9aeaf-6e03-4c11-9e4d-82c5a9d2f100 tag 'loadbalancer' Firewall rule count: 4 Rule ID : 1024 Rule : inout protocol any stateless from ip 192.168.1.2 to ip 124.124.124.124 interface uuid 93676e05-2ca1-45f5-b84f-0bd9a704307c drop Rule ID : 1022 Rule : inout protocol any from any to ip 172.31.4.70 interface uuid 93676e05-2ca1-45f5-b84f-0bd9a704307c accept Rule ID : 1021 Rule : inout protocol any stateless from any to any interface uuid 93676e05-2ca1-45f5-b84f-0bd9a704307c drop Rule ID : 1020 Rule : inout protocol any from any to any accept |
8. 이 후 파일 다운로드 실패
SNAT IP Address(172.31.3.254) → Back-end Server IP Address(172.31.1.51)간 Connection의 Firewall Rule ID가 0에서 1021로 변경되면서 Connection이 예기치 않게 종료
C:\>curl.exe "http://172.31.5.70/downloads/test.txt" -o test.txt % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 57 10.0G 57 5888M 0 0 49.8M 0 0:03:25 0:01:58 0:01:27 0 curl: (18) transfer closed with 4563219935 bytes remaining to read |
이는 NSX Firewall은 Packet Filtering(https://man.freebsd.org/cgi/man.cgi?pf)을 기반으로 하는데 위에서 문제 재현을 한 것처럼 Any-Any Drop Rule이 있는 상태에서 Rule에 대한 변경이 이뤄질 때, 내부적으로 Packet Filtering 관련 Flag가 올바르게 설정되지 못하면서 예기치 않게 Rule ID가 잘못 변경되는 경우로 확인됩니다.
문제 증상은 3.2.4에서 이미 Fix 되어 Release가 되었고, Workaround로는 Any-Any Drop Rule 상단에 SNAT IP Address → Back-end Server IP Address로 향하는 Traffic을 Allow 처리하는 Rule을 추가함으로써 해결할 수 있습니다.