____ ____ _ _ ____
| _ \ _ _ / ___| \ | / ___|
| |_) | | | | | _| \| \___ \
| __/| |_| | |_| | |\ |___) |
|_| \__, |\____|_| \_|____/
|___/
Python으로 구현한 DNS 기반 GSLB 서버입니다.
DNS-based GSLB server implemented in Python.
GSLB(Global Server Load Balancing)란 DNS 프로토콜을 응용한 기술로, DNS 응답을 이용해서 서버의 부하를 분산시키는 로드 밸런싱 기법입니다.
하나의 서비스에서 부하 분산을 위해 여러 서버를 사용하는 경우, 단순히 DNS에 A 레코드를 여러 개 등록할 수 있습니다. 하지만 레코드 기반 로드 밸런싱은 클라이언트에서 랜덤으로 선택되므로, 서버의 장애에 빠르게 대응할 수 없고, 단순한 라운드 로빈 기법 밖에 사용할 수 없습니다. GSLB를 이용하면 실시간 Health Check를 통해 서버 상태를 모니터링하고, 장애 서버를 자동으로 제외하며, 다양한 로드 밸런싱 알고리즘으로 트래픽을 분산할 수 있습니다.
이 외에도 다양한 장점이 있습니다:
- 지리적 트래픽 분산: 클라이언트의 물리적 위치에 가까운 리전 또는 데이터 센터로 지역 기반 트래픽 분배
- 자동 장애 감지: Health Check를 통한 실시간 서버 상태 모니터링 및 장애 서버 자동 제외 (자동 failover)
- 무중단 운영: 서버 점검/교체 시 해당 멤버만 비활성화하면 서비스 중단 없이 운영 가능
- 수평 확장: 서비스 멤버 추가/제거만으로 서버 풀(pool) 확장/축소 가능
- 로드 밸런싱 알고리즘: Round-Robin, Weighted Round-Robin, First-Available, Priority 등 다양한 알고리즘 지원
- DNS 계층에서 투명하게 동작: 표준 DNS 프로토콜을 그대로 사용하므로 클라이언트/애플리케이션 변경 불필요
- Hysteresis 모니터링: Health Check에서 상태 플래핑 방지를 위한 rise/fall 임계값 지원 (일시적 장애에 의한 상태 변경 방지)
PyGNS는 DNS 서버 위에 GSLB 기능이 구현되어 있어, 기존 BIND와 호환되는 Zone 파일을 그대로 사용할 수 있으며, 일부 레코드만 GSLB로 제공할 수 있습니다.
- 모든 네트워크 통신은 비동기로 처리 (asyncio 기반 단일 스레드 비동기 아키텍처)
- Pool/Member 단위 활성화/비활성화 제어
- GSLB 도메인과 Zone 파일 간 레코드 충돌 자동 검증
- SIGTERM/SIGINT 시그널 기반 Graceful Shutdown
- 설정 검증 모드 지원 - 서버 실행 없이 설정 파일 유효성 검사
- 주요 레코드 타입 지원 (A, AAAA, CNAME, MX, NS, SOA, TXT 등)
- UDP 및 TCP Query 모두 지원
- UDP EDNS0 지원 (RFC 6891) - UDP 페이로드 크기 확장 (기본 1232bytes)
- TCP Pipelining 지원 (RFC 7766)
- Negative Caching 지원 (RFC 2308) - NXDOMAIN/NODATA 응답에 SOA 레코드 포함
- 응답 크기 초과 시 단계적 축소 및 TC Flag 설정 지원
- BIND 호환 Zone 파일 지원
- Longest-Matching 방식의 다중 Zone 지원
- 멤버(서버) 선택 알고리즘:
round-robin: 멤버를 순차 순환, 카운터 기반 균등 분배weighted-round-robin: 가중치(weight) 비율로 확장한 리스트에서 라운드 로빈first-available: 첫 번째 가용 멤버 사용 (Active-Standby 구성)priority: 우선순위 기반 선택 (동일 우선순위는 라운드 로빈)random: 가용 멤버 중 무작위로 선택
- Fallback 정책: (모든 멤버 DOWN 시)
none: 빈 Answer (NODATA) + SOA 반환 (트래픽 차단)all: 전체 멤버를 TTL=0으로 반환 (캐시 방지 및 복구 시 즉시 전환) (기본값)
- Health Check:
- HTTP/HTTPS 기반 서버 상태 확인
- Hysteresis 상태 전환 - rise/fall 임계값을 통한 anti-flapping
- Pool 레벨 기본 설정 + Member 레벨 개별 오버라이드
- TCP 커넥션 풀 사용 및 동시 연결 수 제한
- 초기 실행 시, 랜덤 지연으로 순간 부하 방지
- 초기 서버 상태는 가용으로 간주하여 빠른 서비스 시작
- Python 3.11+ 버전이 설치되어 있어야 합니다.
- Linux에서는 53번 포트를 열기 위해 root 권한이 필요합니다.
- Windows에서 시스템 서비스(Dnscache)가 0.0.0.0:53를 사용중인 경우 127.0.0.1로 테스트할 수 있습니다.
- 아래 스크립트를 이용하면, Python 가상 환경 및 패키지 설치를 자동으로 진행합니다.
- Windows:
gns.bat(orgns.bat -b 127.0.0.1) - Linux:
sudo ./gns.sh - macOS:
./gns.sh
- Windows:
| Option | Description | Default |
|---|---|---|
-b, --bind |
서버 IP | 0.0.0.0 |
-p, --port |
서버 포트 | 53 |
-z, --zone-dir |
Zone 파일 디렉터리 | ./config/zone |
-g, --gslb-dir |
GSLB 설정 디렉터리 | ./config/gslb |
-l, --log-level |
로그 레벨 (DEBUG, INFO, WARNING, ERROR) | INFO |
--edns-max-payload |
UDP EDNS0 최대 페이로드 | 1232 |
--hc-initial-delay |
Health Check 초기 랜덤 지연 최대값 (초) | 3 |
--hc-conn-limit |
Health Check 최대 동시 연결 수 | 128 |
-c, --check-configs |
설정 검증 후 종료 | - |
domain: gslb.test.com # GSLB 도메인 (FQDN, trailing dot은 생략 가능)
ttl: 10 # DNS 응답 TTL (초, 기본값: 10)
algorithm: round-robin # 로드 밸런싱 알고리즘
fallback: all # 모든 멤버 DOWN 시, Fallback 정책 (기본값: all)
health_check: # Pool 레벨 헬스체크 설정
protocol: http # http | https
port: 80 # 포트 (기본값: 80)
url_path: /health_check.html # URL (기본값: /)
interval: 10 # 헬스체크 주기 (초, 기본값: 10)
timeout: 5 # 응답 타임아웃 (초, 기본값: 5)
expected_status: [200, 204] # 정상 판정 HTTP 상태 코드 (기본값: [200, 204])
rise: 2 # UP 상태 전환에 필요한 연속 성공 횟수 (기본값: 2)
fall: 3 # DOWN 상태 전환에 필요한 연속 실패 횟수 (기본값: 3)
members:
- address: 127.0.0.10 # 서버 IP 주소 (필수)
# weight: 10 # 가중치 (weighted-round-robin용, 기본값: 10)
# priority: 5 # 우선순위 (priority용, 낮을수록 높은 우선순위, 기본값: 5)
# enabled: true # 활성화 여부 (기본값: true)
comment: "Server 1" # 멤버 설명 (선택)
# health_check: # 멤버별 헬스체크 오버라이드
# port: 8080
# url_path: /status
- address: 127.0.0.20
comment: "Server 2"
- address: 127.0.0.30
comment: "Server 3"$ dig @localhost ns1.test.com
...
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;ns1.test.com. IN A
;; ANSWER SECTION:
ns1.test.com. 3600 IN A 10.20.30.40
$ dig @localhost gslb.test.com +short
10.10.10.10
$ dig @localhost gslb.test.com +short
20.20.20.20
$ dig @localhost gslb.test.com +short
30.30.30.30
$ for i in $(seq 1 100); do dig @localhost gslb.test.com +short; done | sort | uniq -c
33 10.10.10.10
33 20.20.20.20
34 30.30.30.30
전체 테스트 케이스와 결과는 test_result.txt 파일을 참고하세요.
$ ./test.sh
[*] Starting PyGNS server on 127.0.0.1:53...
[+] PyGNS server started! (PID: 11504)
...
[*] Total: 120 / Pass: 120 / Fail: 0
[PASS] RESULT: ALL TESTS PASSED
- GSLB에 AAAA 레코드 지원 추가
- GeoIP 및 ECS (Client Subnet) 구현
- 설정 파일 Hot Reload 구현
- TCP/ICMP에 대한 Health Check 구현
- Zone 전송 및 위임 구현
- MIT License