Information Security Study

240206 도커 네트워크(bridge 조회, 내부 망 host 등록, 브릿지/오버레이, 사용자 정의 네트워크) 본문

네트워크 캠퍼스/Docker

240206 도커 네트워크(bridge 조회, 내부 망 host 등록, 브릿지/오버레이, 사용자 정의 네트워크)

gayeon_ 2024. 2. 6. 16:03

bridge 자체 조회

 

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로 연결 대역을 확인할 수 있다.

network-1
network-3

 

위쪽에서 새로 생성한 게이트웨이인 hostos1 에 연결된 것을 볼 수 있다.

 

 

 

브릿지 입장에서 inspect를 수행해 보았다.

$ docker network inspect mynetwork

 

 

하단에 연결 컨테이너들을 볼 수 있다.

 

 

컨테이너 내역을 시각화하면 위와 같다.

 

 

 

자세한 목록은 brctl show로 확인한다.

 

2개의 인터페이스를 갖는다.

 

컨테이너는 무조건 하나당 하나의 가상이더넷을 가지기 때문에 컨테이너 두 개가 띄워진 현재는 위와 같이 설정된다.

 

 

내부 컨테이너 간 핑을 보내봤다.

 

network-1 의 bash창에서

# ping -c 2 network-2

입력시 아이디를 볼 수 있다.

 

 

같은 망 내에서는 아이피 주소가 아니라 컨테이너 이름만 적어도 처리가 가능하다.

 

핑을 보내면 network-3.mynetwork 과 같이 소속과 함께 아이피주소가 나온다.

 

사용자 정의 네트워크는 자체적으로 DNS를 구성해주기 때문에 도메인까지 알아서 구성된다.

 

 

※ 이름만으로도 조회가 가능한 이유

원래 컨테이너 이름만 가지고는 당연히 아이피를 조회할 수 없지만

같은 커스텀 네트워크 내부에서는 예외적으로 docker DNS가 구축되기 때문에

컨테이너 이름만으로도 조회가 가능하다.