Information Security Study
240206 도커 네트워크(bridge 조회, 내부 망 host 등록, 브릿지/오버레이, 사용자 정의 네트워크) 본문
240206 도커 네트워크(bridge 조회, 내부 망 host 등록, 브릿지/오버레이, 사용자 정의 네트워크)
gayeon_ 2024. 2. 6. 16:03bridge 자체 조회
docker network ls 조회 시 나오는 bridge -> 기본 브릿지
docker0 위에 얹혀져 있다.
$ docker network inspect bridge
: 브릿지 자체에 대해 inspect
IPAM 내부에 네트워크 전체 대역에 대한 내용이 나온다.
그 밑에는 Containers 부분이 있는데 여기에는 할당된 컨테이너 목록을 볼 수 있다.
Veth
- 두 네트워크 네임스페이스 사이의 연결을 위해 동작하는 리눅스 네트워킹 인터페이스다.
vetheernet
- 각 네임스페이스에 단일 인터페이스를 가지는 전이중 링크이다.
- 양방향 통신이 가능하다.
- 한 인터페이스의 트래픽을 다른 인터페이스로 전해주는 역할을 한다.
- 도커 네트워크 생성시 veth를 이용해 네임스페이스간 명시적 연결을 제공한다.
- Container의 Eth는 veth보다 기본적으로 1 작은 값으로 연결된다.
위 명령어로 확인할 수 있는 값들은 아래의 명령어로 os단에서 볼 수 있다.
$ sudo cat /sys/class/net/veth및번호/ifindex
veth및번호는 brctl show로 interfaces 번호를 확인해주면 된다.
network-14의 bash로 진입해둔 상태라면 아래 명령어로 조회할 수 있다.
$ cat /sys/class/net/eth0/iflink
해당 명령어는 도커에서 지원하지는 않지만 기반기술이 리눅스 네트워크이기 때문에 가능하다.
docker0는 기본적으로 아이피를 172.17.0.1 로 사용하지만
외부에서는 172.17 대역을 쓰지 않으므로 이를 보완하기 위해 NAT를 사용한다.
어떤 서버의 아이피주소를 다시 내부아이피로 변환해줘야 하는데 이 때 매핑되는 주소를
iptables라는 명령어로 조회가능하다.
$ sudo iptables -t nat -L -n
위 이미지와 같이 0.0.0.0/0로 접속하면 연결되는 포트번호 등이 나온다.
0.0.0.0/0은 외부 접속자 누구라도 접속 가능하다는 의미이다.
내부망 host들 상호간 등록하기
아이피 주소가 아닌 host1, host2의 이름으로 통신할 수 있다면 편한 것이다.
해당 작업 수행에 필요한 테이블 등록을 할 것이다.
$ sudo vi /etc/hosts
위 파일을 확인하면 localhost와 hostos1의 자기 주소만 등록되어 있다.
hostos1, hostos2의 192로 시작하는 아이피 주소를 작성한뒤 저장한다.
이제
$ ssh 계정명@host명
을 입력하면 제어할 수 있다.
host2의 터미널에서 w를 입력해보면 host1이 접속 중인 것을 확인할 수 있다.
host1에서 host2로 접속했기 때문에 굳이 host2의 터미널에서 하지 않고 host1 터미널에서 확인해도 된다.
컨테이너 간에도 위와 같이 VM간 호스트 연결과 비슷한 작업을 할 수 있다.
위 명령어 중 --add-host=host명:ip주소는 container 의 /etc/hosts에 host명:ip주소 를 매칭해서 저장한다는 의미이다.
dns등록은 위와 같이 해주면 된다.
--dns=아이피주소 → DNS서버의 ip주소를 /etc/resolv.conf에 등록해준다.
대역은 168.126.63.1 ~ 3 / 8.8.8.8 이다.
+) 네트워크 관련해서 지정할 수 있는 옵션
--expose=포트번호
: 방화벽 열기처럼 해당 포트로의 접속을 외부에 공개한다
--net=bridge 혹은 none 혹은 host
: constainer의 네트워크 설정이다. bridge는 docker0이다.
-h, --hostname=”호스트이름”
: host의 이름을 설정한다. pid가 디폴트값이다.
-P, --publish-all=true 혹은 false
: 포트바인딩시 호스트측 접근 포트를 랜덤으로 지정한다.
-p host포트:컨테이너포트, --publish published=host포트, target=타겟포트
: 지정 포트 바인딩
--link=컨테이너명:컨테이너아이디
: 동일 host의 다른 컨테이너에서 이름으로 연결가능하게 지정한다.
-P, --expose 등을 활용하고 조회해봤더니 아래와 같이 나온다.
기본적으로는 history 등을 통해 Dockerfile에 설정된 포트를 노출하는게 제일 중요하다.
포트바인딩 자체는 알아서 32770:80, 32769:30000
으로 배정한 것을 볼 수 있다.
docker proxy로 연결된 것을 다시 확인할 수 있다.
36896번 pid로 도커 프록시가 돌고 있고 해당 프록시가 world(0.0.0.0)의 32770번 포트로 접속하는 것을
172.17.0.9의 80번 포트로 연계해주는 것을 볼 수 있다.
브릿지와 오버레이의 차이
bridge는 기본적으로 내부망으로 진입할 수 있는 진입점으로 기능한다.
하지만 bridge는 자기 호스트 내부망만을 담당한다.
따라서 브릿지 간 통신(외부 호스트)끼리 연결하기 위해서는 overlay가 추가로 필요하다.
이는 도커 스웜을 통해 구현할 것이다.
도커 사용자 정의 네트워크 구성
그동안은 자동으로 생성된 브릿지를 활용했는데
사실 docker0는 기본기능라 빠진 기능이 꽤 있어서 사용자 맞춤 네트워크를 구성해보도록 할 것이다.
도커는 기본적으로 Host OS와 bridge간 연결을 하고
--net 옵션으로 네트워크 설정이 가능하다.
$ docker network create
명령을 이용해 사용자 정의 bridge network 생성이 가능하다.
사용자 정의 네트워크에 연결하는 경우
- 컨테이너명이나 ip주소로 서로 통신이 가능하다.
- overlay 네트워크를 구성하면 host os간에도 연결이 가능하다.
--net에 줄 수 있는 옵션
bridge
: 브릿지 접속을 하도록 설정
none
: 네트워크 외부 노출을 하지 않음
container:컨테이너명이나아이디
: 다른 컨테이너의 네트워크 활용(다른컨테이너 대역을 빌림)
host
: 컨테이너가 host os의 네트워크를 함께 쓰도록 설정
macvlan
: 물리 네트워크에 컨테이너 mac주소를 통한 직접 연결 사용
NETWORK
: 기타 사용자 정의 네트워크 활용
--net에 줄 수 있는 옵션 실습
먼저 포트포워딩 정보 없이 컨테이너를 띄운다.
$ docker run -d --name=nginx_host --net=host nginx:1.25.0
grep 으로 확인해 보면 연 적도 없는 80번 포트가 열려있다.
nginx:master라고 되어있어 호스트 주소로 바로 도는 것을 알 수 있다.
$ curl localhost:80
(위에서 80번 포트 생략 가능) 아래와 같이 nginx가 그냥 호스트 주소로 도는 것을 볼 수 있다.
nginx가 포트포워딩 없이 호스트에서 바로 열린 것이다.
nginx의 80번 포트에 대한 pid를 아래와 같이 조회해보면
host 내부 프로세스처럼 잡히는 것을 볼 수 있다.
host대역을 사용해 도는 nginx 컨테이너의 ip를 확인했다.
$ docker inspect nginx_host | grep -i ipa
해당 컨테이너는 위와 같이 자체적인 ip주소를 가지지 않는다.
host의 ip를 쓰기때문에 따로 배정받을 필요가 없는 것이다.
이는 docker0를 쓰지 않는다는 의미이다.
사용자 정의 네트워크 만들고 연결해보기
network를 실제로 생성해 볼 것이다.
$ docker network create mynetwork
네트워크를 생성한 뒤
$ docker network ls
로 목록을 조회할 수 있다.
아무 옵션도 주지 않고 생성했을 때는 bridge로 만들어진다.
route를 입력해서 현재 ip routing table을 조회해 보았다.
위와 같이 인터페이스명이 br로 시작하는 브릿지가 생성되었다.
$ ifconfig
입력시 제일 상단에 해당 인터페이스명이 조회된다.
$ docker network inspect 이름혹은networkid
위 명령어로 자세한 네트워크 상황을 확인할 수 있다.
해당 네트워크 브릿지에 2개의 컨테이너를 연결해서 관찰해 볼 것이다.
먼저 터미널을 2개 더 띄워서 각각 bash에 접속한다.
$ docker run --net=mynetwork -it --name=network-1 ubuntu:14.04 bash
$ docker run --net=mynetwork -it --name=network-2 ubuntu:14.04 bash
그리고 ifconfig로 각각 어떤 ip를 배정받았는지 확인한다.
route로 연결 대역을 확인할 수 있다.
위쪽에서 새로 생성한 게이트웨이인 hostos1 에 연결된 것을 볼 수 있다.
브릿지 입장에서 inspect를 수행해 보았다.
$ docker network inspect mynetwork
하단에 연결 컨테이너들을 볼 수 있다.
컨테이너 내역을 시각화하면 위와 같다.
자세한 목록은 brctl show로 확인한다.
2개의 인터페이스를 갖는다.
컨테이너는 무조건 하나당 하나의 가상이더넷을 가지기 때문에 컨테이너 두 개가 띄워진 현재는 위와 같이 설정된다.
내부 컨테이너 간 핑을 보내봤다.
network-1 의 bash창에서
# ping -c 2 network-2
입력시 아이디를 볼 수 있다.
같은 망 내에서는 아이피 주소가 아니라 컨테이너 이름만 적어도 처리가 가능하다.
핑을 보내면 network-3.mynetwork 과 같이 소속과 함께 아이피주소가 나온다.
사용자 정의 네트워크는 자체적으로 DNS를 구성해주기 때문에 도메인까지 알아서 구성된다.
※ 이름만으로도 조회가 가능한 이유
원래 컨테이너 이름만 가지고는 당연히 아이피를 조회할 수 없지만
같은 커스텀 네트워크 내부에서는 예외적으로 docker DNS가 구축되기 때문에
컨테이너 이름만으로도 조회가 가능하다.