인트로
----
추가사항입니다. 들어가기에 앞서 https://d-life93.tistory.com/466 이 글을 먼저 보시는 것을 추천드립니다.
----
요즘은 보통 쿠버네티스를 이용해서 서버 구축을 하니 이 글이 필요 없을 수도 있습니다.
다만 저와 같이 순수한 도커 만을 이용할 경우 발생하는 문제와 해결 방법에 대해 경험을 공유하고자 합니다.
주의 도커와 네트워크에 대해 처음으로 공부하면서 문제점을 고치며 서버 구축을 했기 때문에 틀린 부분, 또는 지식적으로 부족한 빈틈이 많을 수 있습니다.
그렇기 때문에 주저리 주저리 적어 놓은 이야기를 보는 것보다 해결했던 결과들만 보는 것도 나쁘진 않겠네요!
Linux 시스템의 보안을 강화하고자 UFW(방화벽)을 적용하고자 설정 시
- Docker에는 UFW 방화벽이 적용이 되지 않는 문제
- Docker Container1 과 다른 Container2의 통신 문제
- 다른 서버에 요청할 때 발생하는 문제
앞으로 작성할 것은 위 문제들의 과정, 해결 방법입니다.
이 문제를 해결하기 위해서는 네트워크에 대한 약간의 지식, 구조에 대해 알아야 했습니다.
iptables, ufw, docker, router, host주소와 docker network 주소가 왜 다른지 이해할 수 있는 정도?
문제 및 해결 방법
우선 도커의 기본 네트워크 구조에 대해 제가 알아본 느낌은 이러했습니다.
- 물론 네트워크에 대해서 eth, docker0, gateway, veth, bridge 등등 더욱 다양한 개념이 많이 있는데 그것들은 찾아서 공부해보심이....
Docker의 장점은 Container화 하는 방식을 이용함으로서 마이크로 서비스를 상용화 하기 편한 장점이 있는데요, 이 컨테이너들의 상호 소통을 위해 docker network가 존재하고 네트워크에 대한 필터링 정책, 규칙, 프로토콜 상태 추적, 라우팅 등등을 관장하는 iptables을 이용해 직접 통제하고 있습니다.
- iptables는 linux firewall 즉 리눅스의 방화벽이라고 생각하면 됩니다.
위 상태에서 iptables를 손쉽게 관리할 수 있는 UFW를 적용하면 어떻게 되는지 보겠습니다.
- UFW는 iptables를 직접 관리하기 위해서는 다양한 지식이 필요하므로 러닝 커브가 높기 때문에 단순화된 방화벽이지만 필수의 기능은 모두 가지고 도구 입니다.
우선, UFW를 실행 및 정책을 적용 시켜 보겠습니다. 다음은 여러가지 예시를 적어봤습니다.
sudo ufw enable # ufw 활성화
sudo ufw allow from 146.44.0.0/16 # 146.44.0.0 ~ 146.44.255.255 대역까지 포트를 포함 전부 허락한다
sudo ufw deny from 198.66.5.0/24 # 198.66.5.0 ~ 198.66.5.255 대역까지 포트를 포함 전부 부정한다
sudo ufw allow 22/tcp # 22번 포트에 대해 tcp protocol로 연결을 허락한다
sudo ufw deny 80 # 80번 포트에 대해 부정한다
sudo ufw default allow outgoing # 기본적으로 나가는 트래픽에 대해 허용한다
sudo ufw default deny incoming # 기본적으로 들어오는 트래픽에 대해 부정한다
#sudo ufw default allow routed # 기본적으로 라우트를 허용한다
sudo ufw reload # 정책을 추가하면 반드시 ufw reload를 해주어 반영시켜야 한다
sudo ufw logging on # ufw에 대한 감시, 방어, 허용된 내역을 로그로 저장시켜준다
UFW + Docker에 대한 구성을 이미지로 보고 싶어 찾아봤는데 없어서 뇌피셜로 한번 그려봤습니다.
그림을 보면 알겠지만 도커는 직접 iptables를 바라보기 때문에 UFW에 등록되는 정책에 구애 받지 않습니다.
그래서 Docker의 이러한 특성을 알지 못했던 저의 경우 이런 생각을 했습니다.
분명 UFW를 구동 시키고 SSH port를 등록하고 블랙리스트도 등록한 상태인데 접속이 가능하네? SSH 등록한 것은 방화벽이 잘 작동되는데.......?
여튼 위와 같은 Docker 특성에 대해 알게 된 후 Docker가 UFW 보안이 적용되기 위해 해결 방법을 검색해본 결과 도커 구동 시 { "iptables" : false } 를 적용해서 iptables와의 직접적인 관계를 끊으면 UFW 보안 정책의 통제를 받는다는 것이었습니다. *iptables를 끊을 경우 문제점도 있다는 것을 보통 함께 적어 놓습니다.
리눅스에서 위 방법을 다음과 같이 적용해보겠습니다.
docker daemon 파일 작성
sudo vim /etc/docker/daemon.json
{
"iptables" : false
}
위 파일을 작성 및 저장하고 docker를 재시작 합니다.
sudo systemctl start docker
위 방법을 적용할 경우 다음 이미지와 같이 적용 되어 첫번째 문제가 해결되게 됩니다.
- Docker에는 UFW 방화벽이 적용이 되지 않는 문제
위 문제를 해결 후 발생되는 문제가 있습니다.
- Docker Container1 과 다른 Container2의 통신 문제
사실 이 문제는 제가 도커 네트워크에 대한 이해가 없어 도커 네트워크를 사용하지 않아 발생한 문제입니다.
지금에 와서 도커에 이런 기능이 있었구나?를 알게 되고 이해했는데, 개발하는 동안 저는 도커를 사용하는 경우가 아닌 일반적인 통신 방식을 응용해서 사용했습니다.
docker를 잘 사용하시는 분이라면 위 문제가 발생하지 않았을 것이라 생각됩니다. 도커에 대해 잘 모른다면 저와 같은 방식을 사용하지 않을까 싶은데, 저와 동일한 문제 발생 시 해결하시라고 방법을 작성해 놓는 것입니다.
그렇기 때문에 웬만하면 도커 네트워크를 이용하는 방식으로 코드 또는 구조를 바꾸시길 추천 드립니다.
예시 Host, Port 번호
- Backend+Frontend = 100.0.0.0:10000
- Database = 100.0.0.0:10001
- Container = 100.0.0.0:10002
상황은 다음과 같습니다.
UFW를 적용한 상태에서 데이터베이스 컨테이너에 연결하여 로그인하는 경우 발생한 문제.
1번 문제를 해결하면서 docker와 iptables를 끊었다고 작성했었습니다.
이게 문제로 발생하게 되는데요
iptables를 사용하지 않는 경우 docker는 docker proxy을 이용해서 100.0.0.0:10002 컨테이너에 위치한 데이터베이스를 연결하려 하면 UFW 정책에서 docker network에 대한 ip 대역의 허가가 필요합니다.
왜냐? 다음을 보시죠
UFW 로그를 확인해보면 다음과 예시와 같이 나와 있을 텐데요.
sudo tail -f /var/log/uft.log
[UFW BLOCK] ...... SRT=172.19.0.2 DST=172.19.0.3 ....
SRT가 요청을 하는 IP주소, DST가 요청을 받는 IP 주소입니다.
저의 경우 데이터베이스 연결 부분에서 계속 에러가 발생하여 확인해보니
실제 작성 해놓은 호스트와 포트 번호는 100.0.0.0:10002 인데,
백엔드 서버상에서 Database 연결 시 자동적으로 위와 같이 docker network의 172.19.0.0/16 대역을 통해 요청하고 있었습니다.
아직 지식이 짧아 유추하기엔 iptables를 사용하지 않아서 그런 것이 아닌가? 판단됩니다.
결론적으로 다음과 같이 docker network 대역을 ufw에 정책을 추가해주면 통신이 가능했습니다.
sudo ufw allow from 172.19.0.0/16
sudo ufw reload
- 다른 서버에 요청할 때 발생하는 문제
이 문제는 다음과 같은 상황이었습니다.
Main Server에서 발생하는 요청을 Sub Server에 요청하고 결과 값을 반환 받아야 했습니다.
그런데 아무리 요청해도 되지 않네......... ?
- Sub Server에 요청을 받는 프로그램에서 오류가 발생한 것인가?
- 아니었습니다. 아예 실행된 내역이 없었습니다.
- 그리고 제 코드는 테스트해서 정상 가동되는 걸 확인했거든요!
- Sub Server에 방화벽에서 막히는 것인가?
- 아니었습니다. 로그 확인 결과 BLOCK 되지 않았습니다.
그렇다면 .... Main Server 문제... . ?
- Main Server에서 요청을 하긴 한 건가?
- 요청하는 로그가 분명 남아있었고 실패한 내역도 있었습니다.
- 설마 .... Main Server 방화벽에 스스로 막힌 것인가 ?
- Log 확인 결과 자체적으로 BLOCK되고 있었습니다.
[UFW BLOCK] ...... SRT=172.19.0.2 DST=101.0.0.0 ....
- 분석해보면 Main Server의 Docker Network 주소인 172.19.0.2에서 Sub Server인 101.0.0.0으로 요청을 보내는데 BLOCK이 걸렸습니다.
- ufw의 default outgoing 값이 allow 인데?? 왜 자체에서 요청이 못나가고 있지....?
이유는 iptables를 끊음으로서 라우팅 기능이 손실 된 것이 문제라고 생각되는데요
그렇게 생각한 이유는 다음과 같습니다.
다음 명령을 실행해보면 UFW의 현재 상태, 정책, 기본 값에 대해 상세히 보여줍니다.
sudo ufw status verbose
UFW 기본값이 다음과 같이 설정되어 있을 겁니다.
- Default : deny(incoming), allow(outgoing), deny(routed)
위 값 중에 routed를 허용해서 UFW의 route 기능을 활성화 하니
Main Server에서 Sub Server(101.0.0.0)로의 Request 요청이 가능했습니다.
sudo ufw default allow routed
sudo ufw reload
마무리
위 내용들을 찾지 못한 것인지 아니면 없는 것인지 갓 구글 검색 어느 곳에도 발견하지 못해서 직접 해결해본 경험을 작성해봤습니다.
지식이 얕아서 거의 경험 위주, 추론하는 방식으로 풀어나갔더니 양질의 글은 아닌 것 같네요
그래도 저와 같은 문제로 고생하고 계시는 분이 우선 정신 건강을 위해 이 글의 해결 방법으로 해결하실 수 있으면 좋겠네요
그리고 따로 더 공부해보시는 것을 추천 드립니다.
또한 틀린 부분이나 개선할 수 있는 부분이 보이는 고수님들은 이 글을 읽는 사람들에게 도움이 되도록 댓글 부탁 드립니다.
'Programming > Infrastructure' 카테고리의 다른 글
Docker + UFW+ IPTABLES 방화벽 적용 (6) | 2022.05.13 |
---|