KANS 1주차 - 컨테이너 격리 & 네트워크 보안
학습 환경 구축 및 접속
Image : ubuntu 22.04
machine type : t3.small
도커 설치 및 확인
# [터미널1] 관리자 전환
sudo su -
# 도커 설치
curl -fsSL https://get.docker.com | sh
# 도커 정보 확인 : Client 와 Server , Storage Driver(overlay2), Cgroup Version(2), Default Runtime(runc)
docker info
docker version
# 도커 서비스 상태 확인
systemctl status docker -l --no-pager
위 명령어로 간단히 도커를 설치 할 수 있다.
도커 데몬이 Unix socket에 바인딩 되어 있다는 것을 이번에 알게 되었는데, 해당 Unix socket은 root 유저가 소유하고 있는 것으로 다른 유저는 sudo 명령어를 통해서만 사용할 수 있다.
그렇기에 root 유저가 아닌 ubuntu 유저의 경우 docekr info 커맨드 실행 시

ERROR: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.47/info": dial unix /var/run/docker.sock: connect: permission denied
/var/run/docker.sock 에 대한 권한 거부로 에러가 발생한다. 클라이언트의 정보는 가져올 수 있지만 Server의 데이터를 가져오는데 실패한 것
ubuntu@MyServer:~$ ls -alh /var/run/docker.sock
srw-rw---- 1 root docker 0 Aug 31 22:41 /var/run/docker.sock
해당 파일에 대한 정보를 보면 root 유저의 소유임을 확인할 수 있다.
파일 사이즈가 0인 이유는 메시지가 쌓이는 것이 아닌 바로 커널로 전달되기 때문.
sudo su -
docker info
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
root유저로 변경 후 같은 커맨드 실행시 Server의 정보도 문제 없이 가져올 수 있다.
처음에 내가 가진 질문은 다음과 같았다. Unix Socket의 이점을 알고 싶었기 때문이다.
그러나 나의 질문은...
Q. 소켓통신이 TCP 통신보다 나은 이유?
A. 소켓 통신은 TCP 통신을 포함하는 개념으로, TCP는 소켓을 통해 구현되는 전송 프로토콜입니다. 따라서 "소켓 통신이 TCP 통신보다 낫다"는 표현은 부적절합니다. 대신, 특정 상황에서는 UDP 소켓 (비연결형) 통신이 TCP 소켓 (연결형) 통신에 비해 성능이 더 우수할 수 있습니다. 예를 들어, 실시간 스트리밍 또는 게임과 같이 속도가 중요한 경우 UDP가 더 효과적일 수 있습니다.
Unix Socket 과 TCP Port의 차이
Unix Socket:
- 파일 시스템의 경로를 사용하여 소켓을 생성하며, 일반적으로 같은 호스트 내에서 프로세스 간 통신에 사용됩니다.
- 속도가 빠르고, 오버헤드가 적습니다. 이더넷이나 TCP/IP 프로토콜을 사용하지 않기 때문에 데이터를 직접 전달합니다.
- 일반적으로 로컬 환경에서만 사용됩니다.

TCP Port
- 네트워크를 통해 다른 컴퓨터와 통신할 수 있도록 하는 TCP/IP 프로토콜을 사용합니다.
- 클라이언트와 서버 간의 통신에 일반적으로 사용되며, 인터넷 또는 로컬 네트워크를 통해 연결됩니다.
- 각 프로세스는 특정 포트를 통해 액세스할 수 있으며, 원거리 통신도 가능하지만 속도는 Unix Socket에 비해 느릴 수 있습니다.

소켓에 대한 좀 더 깊은 이해는 다음 영상을 통해 얻을 수 있습니다.
소켓 01 00 소켓의 본질에 대한 이해 (https://www.youtube.com/watch?v=3jQ2dBpiqPo)
도커란?
Docker is a platform designed to help developers build, share, and run container applications.
도커의 정의에 따르면 컨테이너를 만들고, 공유하고, 실행하기 위한 플랫폼이라고 한다. 그렇다면 추가적으로 컨테이너란 무엇인지에 대해 알아볼 필요가 있다.

컨테이너의 정의
컨테이너는 소프트웨어 서비스를 실행하는 데 필요한 특정 버전의 프로그래밍 언어 런타임 및 라이브러리와 같은 종속 항목과 애플리케이션 코드를 함께 포함하는 경량 패키지입니다. - Google Cloud - (Link)
컨테이너의 이점
- 책임 분리 : 운영에서의 이점. 개발자는 어플리케이션 로직에 집중, 운영팀은 배포 및 관리에 집중 가능.
- 워크로드 이동성 : 운영체제와 상관없이 실행가능 하기에 배포의 편리성이 높음.
- 애플리케이션 격리 : 운영체제 수준에서 CPU, Memory, Storage, Network resource를 가상화 하기에 개발자에게 격리된 OS 환경을 제공.
컨테이너와 VM의 차이
- 컨테이너는 VM보다 훨씬 더 경량입니다.
- 컨테이너는 OS 수준에서 가상화되고 VM은 하드웨어 수준에서 가상화됩니다.
- 컨테이너는 OS 커널을 공유하며 VM에 필요한 것보다 훨씬 적은 메모리를 사용합니다.
- 상대적 약한 격리성(Weak Isolation)
컨테이너 격리
다음과 같은 기술들이 계속해서 개발되고 있다.
년도 : 기술
1979 : chroot
2002 : mount
2006 : uts, ipc
2008 : pid, cgroups
2009 : net
2012 : user
2013 : Docker
2015 : Kubernetes
일단 Docker, Kubernetes 말고는 이번에 처음 듣게된 기술들이어서 많이 낯설었다.
chroot
chroot는 Unix 및 Linux 운영 체제에서 사용하는 시스템 호출로, 특정 프로세스와 그 자식 프로세스의 루트 디렉토리를 변경하는 기능을 제공. 그러나 문제는 탈옥이 가능하다는 것. chroot만으로 완전한 보안을 제공할 수 없으며, 해당 프로세스가 기본적으로 루트 권한을 가지고 있다면 여전히 위험이 있다.
Namespace
리눅스 네임스페이스(Linux Namespace)는 커널의 기능으로, 프로세스 간에 리소스(프로세스 ID, 네트워크 인터페이스, 마운트 포인트 등)를 격리할 수 있는 메커니즘입니다. 네임스페이스를 사용하면 다양한 프로세스가 동일한 리소스를 사용하더라도 서로 격리된 환경에서 실행될 수 있습니다.

root@MyServer:~# ls -l /proc/1/ns
total 0
lrwxrwxrwx 1 root root 0 Sep 1 01:15 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 mnt -> 'mnt:[4026531841]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 net -> 'net:[4026531840]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 time -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 uts -> 'uts:[4026531838]'
root@MyServer:~# unshare /bin/sh
# ls -l /proc/1/ns
total 0
lrwxrwxrwx 1 root root 0 Aug 31 22:30 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Aug 31 22:30 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Aug 31 22:19 mnt -> 'mnt:[4026531841]'
lrwxrwxrwx 1 root root 0 Aug 31 22:30 net -> 'net:[4026531840]'
lrwxrwxrwx 1 root root 0 Aug 31 22:20 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Aug 31 22:30 time -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Sep 1 01:15 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0 Aug 31 22:30 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Aug 31 22:30 uts -> 'uts:[4026531838]'

컨테이너 내의 namespace와 호스트의 namespace가 다른 것을 확인할 수 있다.
다만 user의 namespace는 동일하다.
$ ls -alh
...
lrwxrwxrwx 1 root root 0 Aug 31 22:30 user -> 'user:[4026531837]'
$ file user
user: symbolic link to user:[4026531837]

GPT와 함께 추가 탐구를 진행해 보았다.
user 이외는 다른 네임스페이스를 사용중이고, user는 같은 네임스페이스를 사용 중이라는건?

컨테이너 네트워크 & IPTables
일단 용어에 대한 기본적인 정의를 살펴 보겠다.
iptables is a user-space utility program that allows a system administrator to configure the IP packet filter rules of the Linux kernel firewall, implemented as different Netfilter modules. The filters are organized in a set of tables, which contain chains of rules for how to treat network traffic packets. - wikipedia link -
시스템 관리자가 리눅스 커널 방화벽의 IP packet 필터 룰을 구성할 수 있도록 하는 유틸리티 프로그램.

IPTables 주요 기능
- 패킷 필터링:
- IPTables는 네트워크 패킷을 분석하고, 정의된 규칙에 따라 패킷이 허용될지 또는 거부될지를 결정합니다.
- 체인 및 테이블:
- IPTables는 다음과 같은 기본 테이블을 사용하여 다양한 기능을 수행합니다:
- filter: 기본 테이블로, 패킷 허용 또는 차단 기능을 수행.
- nat: 네트워크 주소 변환(NAT) 관련 규칙을 처리.
- mangle: 패킷의 특정 필드를 수정하는 데 사용.
- raw: 연결 추적을 비활성화하고, 패킷을 직접 처리.
- IPTables는 다음과 같은 기본 테이블을 사용하여 다양한 기능을 수행합니다:
- 체인:
- 각 테이블은 여러 체인을 가집니다. 주요 체인은 다음과 같습니다:
- INPUT: 외부에서 들어오는 패킷을 처리.
- OUTPUT: 내부에서 나가는 패킷을 처리.
- FORWARD: 다른 네트워크로 전달되는 패킷을 처리.
- 각 테이블은 여러 체인을 가집니다. 주요 체인은 다음과 같습니다:
- 규칙 정의:
- IPTables의 각 규칙은 소스 IP, 목적지 IP, 프로토콜, 포트 등 다양한 조건을 기반으로 설정할 수 있습니다. 예를 들어:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH 포트 22 허용 iptables -A INPUT -p tcp --dport 80 -j DROP # HTTP 포트 80 차단
- IPTables의 각 규칙은 소스 IP, 목적지 IP, 프로토콜, 포트 등 다양한 조건을 기반으로 설정할 수 있습니다. 예를 들어:
- 상태 추적:
- IPTables는 패킷의 상태를 추적할 수 있는 기능을 제공합니다. 예를 들어, 신규 연결, 이미 established된 연결, RELATED 연결 등을 기반으로 규칙을 설정할 수 있습니다.
- 상태 추적을 사용하면 보다 세밀한 트래픽 제어가 가능합니다:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT # 이미 존재하는 연결의 트래픽 허용