개요
서버를 설치하고, 인프라를 구축하고, 장애를 해결하는 모든 업무의 근간에는 바로 OSI 7계층 이라는 강력한 나침반이 있습니다.
이른으로만 들었던 OSI 7계층을 실제 업무에서 어떻게 활용할 수 있는지,
두 가지 시나리오를 기반으로 랩을 구축하고 직접 해결해보는 실습 프로젝트를 진행해보겠습니다.
Part 1. 공통 랩 환경 구축: 미니 IDC 만들기
두 가지 시나리오를 모두 실습할 수 있는 작은 IDC 환경을 Pnetlab에 먼저 구축하겠습니다.
✅ Step 1: 프로젝트 구성도
IDC는 아주 간단하게 구성할겁니다.
외부 사용자, 내부 서버망, 그리고 보안을 위한 방화벽으로 구성됩니다.
특히 서버망은 방화벽을 통해 Trust 영역과 Untrust 영역으로 분리하여 서버를 배치할 계획입니다.
Trust 영역에는 외부에 노출되어서는 안되는 db
서버와 같은 민감한 서버들을,
Untrust 영역에는 외부에서 접근이 필요한 nginx
등의 웹 서버를 배치할 예정입니다.
이번 실습에서는 Trust에는 DB 서버를, Untrust에는 nginx를 배치하겠습니다.
📢 참고
이번 게시글에서는 네트워크 구성을 위한 실습은 따로 진행하지 않습니다.
시나리오 별 트러블슈팅에 집중하여 실습을 진행할 것이기에 관련 구축 설정이 궁금하시다면 댓글 달아주세요. 추후 업데이트 하겠습니다.
✅ Step 2: 노드 설정
- 1. 서버 노드 (web, db): Ubuntu 이미지를 사용하고 각 서브넷에 맞게 IP를 할당합니다.
web
:sudo apt install nginx
db
:sudo apt install mariadb-server
- 2. 스위치 및 방화벽: 구성도에 맞게 노드 연결하고, L2 스위치에서는 따로 Vlan을 생성하지 않습니다. 기본 vlan(
1
)을 사용하도록 해주세요.- 방화벽에서는 각 대역(
Trust
,Untrust
)을 정의하고 기본적인 설정을 해주시면 됩니다.
- 방화벽에서는 각 대역(
Scenario 1: 신규 서버 설치 후 외부 접속 불가
미션
IDC에 방금 새로 설치한 web
서버(192.168.10.10
)에 대해, 외부 사용자(172.16.10.10
)가 웹 브라우저로 접속할 수 있도록 해야 합니다.
이때 방화벽에서는 웹 트래픽이 들어왔을 때 Untrust
영역에 있는 web 서버의 HTTP/80
, HTTPS/443
포트로 트래픽을 전송합니다.
(포트포워딩 설정을 방화벽에서 구성했다고 가정.)
가상 장애 상황
방화벽 정책이 누락되어 외부에서의 접속이 차단된 상황을 시뮬레이션해 볼 예정입니다.
Layer 1~2: 물리 & 데이터 링크 계층
"케이블은 제대로 꽂았나? 스위치는 서버를 인식하나?"
🕵️♂️ 트러블슈팅
1. web 서버, 스위치, 방화벽 간의 링크가 모두 녹색(Up)인지 확인해주세요.
2. 서버가 연결된 L2 스위치에서 show mac address-table | include [web서버포트]
명령어로 서버의 MAC 주소를 정상적으로 학습하는지 확인해주세요.
현재 untrust
스위치 측에서 연결된 웹 서버의 맥 주소를 정상적으로 학습한 걸 볼 수 있습니다.
💡 예상 결과 및 판단
L1 & L2 구간은 모두 정상입니다.
물리적 연결과 2계층 스위칭에는 문제가 없네요.
"하위 계층은 문제 없어, 위로 올라가자!"
Layer 3: 네트워크 계층
서버까지 가는 길(경로)은 있나? 누가 길을 막고 있는거 아니야!?
🕵️♂️ 트러블슈팅
[가장 중요]
문제 해결의 범위를 좁히기 위해 방화벽 CLI로 접근해주세요. 그리고 그 후에 web
서버로 ping 192.168.10.10
을 실행하여 방화벽과 웹 서버 구간까지의 통신이 정상적인지 확인해야 합니다.
그다음, 클라이언트 PC(172.168.10.10
)에서 web
서버로 ping 192.168.219.200
을 실행하여 클라이언트 구간부터 방화벽 구간까지 통신이 정상적으로 이루어지는지 확인해봅시다.
💡 예상 결과 및 판단
- 1. 방화벽에서 서버로는
ping
이 성공합니다. (방화벽 서버 간 경로 정상) - 2. 클라이언트 PC에서 방화벽까지
ping
이 성공합니다. - 3. 결론: 패킷이 클라이언트에서 방화벽까지는 도달하죠? 하지만 웹 서비스는 접속이 안되는 걸로 보아 방화벽에서 포트를 차단하고 있는 것 같아 보입니다!
Layer 4: 전송 계층
"길은 있는데, 내가 가려는 서비스의 '문(Port)'이 닫혔나?"
🕵️♂️ 트러블슈팅
1. web 서버 터미널에서 ss -lntp | grep 80
을 실행하여 80번 포트가 정상적으로 리스닝(LISTEN
)하고 있는지 확인합시다.
정상적으로 nginx 서비스의 80번 포트를 리스닝하고 있습니다.
2. 클라이언트 PC에서 nmap -e 80 192.168.219.200
을 실행하여 방화벽 측에서 포트포워딩을 웹서버로 해주고 있는지 확인해봅시다.
💡 예상 결과 및 판단
- 서버 측에서는 80번 포트를 열고 요청을 기다리고 있네요.
Nmap
결과는filtered
로 나옵니다. 이는 포트가 닫혀있다기 보다, 방화벽 같은 장비가 응답 자체를 막아 상태를 알 수 없다는 뜻이 됩니다. 3계층에서 내린 결론을 다시 한 번 확인시켜 준거죠.
Layer 7: 응용 계층
방화벽 정책을 열어 길을 터주자!
🕵️♂️ 해결 및 테스트
확인해보니 방화벽에서 HTTP
서비스에 대해 정책이 추가되어 있지 않았습니다!
그리고 nc
명령을 사용하여 방화벽 측에서 정상적으로 웹 서버로 포트포워딩을 진행해주고 있는지 검증해보겠습니다.
성공하네요.
Scenario 2: WEB/DB 서버 간 연동 실패
미션
WEB 서버(192.168.10.10
)가 DB 서버(192.168.10.20
)의 데이터베이스에 접속해야 하는데, 연결이 실패하는 문제를 해결해야 합니다.
가상 장애 상황
보안 정책상 서버 간 통신도 방화벽을 거치도록 구성된 환경에서,
필요한 포트(MySQL/3306
)를 허용하지 않은 상황을 시뮬레이션합니다.
Layer 3: 네트워크 계층
"서버끼리 서로의 존재는 알고 있나?"
🕵️♂️ 트러블슈팅
1. WEB 서버 터미널에서 DB 서버로 ping 192.168.20.10을 실행합니다.
웹 서버에서 DB 서버로 ping이 안나가네요?
💡 예상 결과 및 판단
방화벽 정책 확인해보니 Untrust (DMZ)
-> Trust (Internal)
접근 정책이 아예 없었나 봅니다!
정책은 추가했고 웹 서버에서 DB 서버로 다시 ping
테스트 진행하겠습니다.
성공하네요!
Layer 4: 전송 계층
"DB로 가는 문(3306 포트)이 잠겨 있나 확인해보자!
🕵️♂️ 트러블슈팅
[가장 중요] 1. DB 서버 터미널에서 ss -lntp | grep 3306
을 실행하여 MariaDB가 3306 포트를 정상적으로 리스닝하는지 확인합니다.
서버에서 정상적으로 mysql 포트를 리스닝하고 있네요.
2. WEB 서버 터미널에서 nc -zv 192.168.20.10 3306
명령어로 3306 포트 연결을 직접 시도합니다.
분명 Layer 3에서 MySQL
정책도 추가해줬습니다만 ..
💡 예상 결과 및 판단
먼저 db 서버측에서 sudo tcpdump -i <트래픽_수신받는_인터페이스> src port 3306
를 입력하여 웹 서버에서 요청한 스캔 트래픽이 방화벽을 거쳐서 db 서버로 도착하는지 검증해봅시다.
웹 서버(192.168.10.10
)으로부터 정상적으로 스캔 트래픽이 도착했네요?
그러면 원인은 응용 계층에 있는게 확실하네요!
Layer 7: 응용 계층
위에서 이미 db 서버의 3306
포트가 리스닝되고 있는 것을 확인 했으니 서비스 활성화 문제는 아닙니다.
다른 DBMS도 그런지는 모르겠지만 mariadb
의 경우에는 bind-address
설정 때문에 외부 접속이 막힐 수 있다고 합니다.
DB 서버 측에서 ss
명령을 실행하여 3306
리스닝 주소가 어떻게 되어 있는지 다시 확인해보겠습니다.
sudo ss -tulpn | grep 3306
127.0.0.1:3306
만 보이고 있죠? 이건 로컬 루프백만 허용하고 외부 접속은 거부하겠다는 의미입니다.
이를 해결하기 위해 설정 파일을 수정해야 합니다.
Mariadb 설정 파일에서 bind-address
값을 수정해줍시다.
$ sudo grep -r "bind-address" /etc/mysql/mariadb.conf.d/
/etc/mysql/mariadb.conf.d/50-server.cnf:bind-address = 127.0.0.1
해결 방법: bind-address
를 0.0.0.0
또는 특정 IP로 바꿔 외부 접속을 허용합니다.
[mysqld]
bind-address = 0.0.0.0
그리고 mariadb를 재시작할게요.
sudo systemctl restart mariadb
그리고 다시 nginx에서 nc
명령을 실행해보면 어떻게 될까요?
nc -zv 192.168.10.20 3306
마무리
이 두 시나리오를 통해 OSI 7계층 모델을 기반으로 문제를 해결해나가는 것에 조금 익숙해지셨나요?
이 경험은 앞으로 마주할 더 복잡한 장애 상황에서 더욱 더 빛을 발할 수 있을거에요!