레이블이 ip인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ip인 게시물을 표시합니다. 모든 게시물 표시

overlay network 사용하기

# 들어가기 전에
# overlay network 실제 네트워크가 위에서 동작하는 가상네트워크다.
# overlay network 로 물리적으로 떨어져 있는 네트워크들도 마치 같은 네트워크에 있는 LAN 처럼 취급할 수 있다.
# 종류로 Virtual eXtensible LAN (VXLan)가 있다.
# OSI7계층 중 L2(datalink), L3(network) 에 걸쳐 사용되고, L2 프레임을 캡슐화해 터널링한다.
# MTU(Maximum Transmission Unit)는 패킷이나 프레임단위로 전송할때 최대 크기로 일반적으로 1500byte 으로 설정되는데 VXLan 사용시 캡슐화에 50byte 가 필요하기 때문에 1450byte 로 설정한다.
# ICMP(Internet Control Message Protocol) 는 L3 동작하며 대상 IP 의 상태(이상없는지)를 확인하는 프로토콜이다.
# ARP(Address Resolution Protocol)은 L3 동작하며 IP 주소를 L2의 물리주소(MAC, Media Access Control)주소로 바인딩시키기 위한 프로토콜이다.
# FDB(Fowarding DataBase)는 L2 에서 포워딩을 위해 MAC 주소를 저장하고 있다.


#####


# 테스트 환경 : vagrant ubuntu-1804
HOST_NAME = "ubuntu1804"    # node1 192.168.104.2
HOST_NAME2 = "ubuntu1804-2" # node2 192.168.104.3

# node1,2 각각 접속시 
vagrant ssh ubuntu184
vagrant ssh ubuntu184-2

# vxlan 으로 노드간 통신하기
# node1, node2 는 다음과 같이 구성(연결)할 것이다.
[node1]
pinkns(eth0:12.12.12.2/24) <-> overns(veth1 <-> br0:arp참고 <-> vxlan1:fdb참고) <-> host(eth1:192.168.104.2) <-> 외부
[node2]
pinkns(eth0:12.12.12.3/24),skyns(eth0:12.12.12.4/24) <-> overns(veth1 <-> br0:arp참고 <-> vxlan1:fdb참고) <-> host(eth1:192.168.104.3) <-> 외부

# node1, node2 각각 overns, pinkns 이름의 network namespace(netns) 생성
ip netns add overns
ip netns add pinkns

# node1, node2 각각 network namespace 확인
ip netns

# node1, node2 각각 veth1(overns) <-> eth0(pinkns) 연결(link 생성)
ip link add dev veth1 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns pinkns

# 참고로 ip netns exec overns 대신 overns 에 조인해서 작업할 경우
# 작업후 호스트 network namespace 로 돌아오기 위해 exit 잊지 말자.
# nsenter --net=/var/run/netns/overns

# node1(overns), node2(overns) 에서 ip link 확인
ip netns exec overns ip link

# node1(pinkns) 에서 �eth0 에 mac,ip address 추가
ip netns exec pinkns ip link set dev eth0 address 02:42:c0:a8:00:02
ip netns exec pinkns ip addr add dev eth0 12.12.12.2/24

# node2(pinkns) 에서 eth0 에 mac,ip address 추가
ip netns exec pinkns ip link set dev eth0 address 02:42:c0:a8:00:03
ip netns exec pinkns ip addr add dev eth0 12.12.12.3/24

# node1(overns), node2(overns) 에서 bridge 생성
ip netns exec overns ip link add dev br0 type bridge
ip netns exec overns ip addr add dev br0 12.12.12.1/24

# node1(overns), node2(overns) 에서 ip, link 확인
ip netns exec overns ip a
ip netns exec overns ip link

# node1, node2 에서 vxlan(overns) 생성
# type vxlan : vxlan 타입 생성
# id 42 : vxlan 식별자 42
# proxy : vxlan 이 ARP 요청에 대신 응답하도록 설정
# learning : 커널이 패킷을 파악해 bridge FDB 를 자동으로 설정할 수 있도록 설정
# dstport 4789 : vxlan 터널링에 사용하는 UDP 포트로 4789 사용
ip link add dev vxlan1 netns overns type vxlan id 42 proxy learning dstport 4789

# node1(overns), node2(overns) 에서 veth1 <-> br0 연결
ip netns exec overns ip link set veth1 master br0

# node1(overns), node2(overns) 에서 vxlan1 <-> br0 연결
ip netns exec overns ip link set vxlan1 master br0

# node1, node2 각각 overns, pinkns 의 장치들 모두 power on
ip netns exec overns ip link set br0 up
ip netns exec overns ip link set vxlan1 up
ip netns exec overns ip link set veth1 up
ip netns exec pinkns ip link set eth0 up

# node1(overns) 에서
# 목적지 ip(12.12.12.3),mac(02:42:c0:a8:00:03)를 사용하는 vxlan1 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.3 lladdr 02:42:c0:a8:00:03 dev vxlan1

# node2(overns)에서
# 목적지 ip(12.12.12.2),mac(02:42:c0:a8:00:02)를 사용하는 vxlan1 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.2 lladdr 02:42:c0:a8:00:02 dev vxlan1

# node1(overns), node2(overns) 에서 neighbor 확인
ip netns exec overns ip neighbor show

# node1(overns) 에서
# bridge fdb 설정 추가
# 192.168.104.3 : 목적지 IP
# 42 : 목적지 vni(VXLAN Network Identifier) ID
# 4789 : 목적지 Port
# 다음과 같이 수동으로 설정하면 permanent 하게 유지된다.
ip netns exec overns bridge fdb add 02:42:c0:a8:00:03 dev vxlan1 self dst 192.168.104.3 vni 42 port 4789

# node1(overns) 에서 fdb 설정 확인하면 permanent 표시가 있다.
ip netns exec overns bridge fdb show | grep 02:42:c0:a8:00:03

# node1(overns) 에서 br0, vxlan 에서 패킷 확인시
ip netns exec overns tcpdump -l -i br0
ip netns exec overns tcpdump -l -i vxlan1

# 위에서 vxlan 디바이스 생성 시에 learning 옵션사용했기 때문에 fdb, ARP 정보는 커널에서 패킷 분석해서 설정해준다.
# 하지만 수동설정(permanent)와 달리 aging 으로 인해 일정 시간 지나면 설정이 제거된다.
# node2(overns)에서 다음과 같이 다시 수동으로 변경하면 permanent 하게 설정된다.
ip netns exec overns bridge fdb replace 02:42:c0:a8:00:02 dev vxlan1 self dst 192.168.104.2 vni 42 port 4789

# node2(overns)에서 다시 fdb 설정 확인하면 permanent 가 있다.
ip netns exec overns bridge fdb show | grep 02:42:c0:a8:00:02

# 참고로 overns 의 FORWARD 가 허용으로 되어 있는지 확인
ip netns exec overns iptables -t filter -L | grep -i policy
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)

# node1(pinkns조인 상태) -> node2(pinkns) ping 해보면 응답을 받는다.
ip netns exec pinkns ping 12.12.12.3

# node2(pinkns조인 상태) -> node1(pinkns) ping 해보면 응답을 받는다.
ip netns exec pinkns ping 12.12.12.2



#####


# node1 에 새로운 skyns network namespace 추가하고 통신하기

# node1 에서 skyns 네트워크네임스페이스 추가, mac,ip 등 추가하고 power on
ip netns add skyns
ip link add dev veth2 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns skyns
ip netns exec skyns ip link set dev eth0 address 02:42:c0:a8:00:04
ip netns exec skyns ip addr add dev eth0 12.12.12.4/24
ip netns exec overns ip link set veth2 master br0
ip netns exec overns ip link set veth2 up
ip netns exec skyns ip link set eth0 up

# node1(skyns) -> node1(pinkns) ping 테스트
ip netns exec skyns ping 12.12.12.2

# node1(pinkns) -> node1(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.4

# node2(overns) 에서 fdb 추가
ip netns exec overns ip neighbor add 12.12.12.4 lladdr 02:42:c0:a8:00:04 dev vxlan1

# node1(skyns) -> node2(pinkns) ping 테스트
ip netns exec skyns ping 12.12.12.3


#####


# node3(192.168.104.4) 추가하고 node1,2와 통신하기

# vagrantfile 노드 추가 후 
# HOST_NAME3 = "ubuntu1804-3" # node3 192.168.104.4
# ubuntu1804-3(node3) 만 추가로 띄우기
# vagrant up
# ubuntu1804-3(node3) 접속
vagrant ssh ubuntu184-3

# node3 overns,pinkns, skyns network namespace 추가
ip netns add overns
ip netns add pinkns
ip netns add skyns

# node3 veth1(overns) <-> eth0(pinkns) 연결(link 생성)
ip link add dev veth1 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns pinkns

# node3 veth1(overns) <-> eth0(skyns) 연결(link 생성)
ip link add dev veth2 mtu 1450 netns overns type veth peer name eth0 mtu 1450 netns skyns

# node3(pinkns) 에서 eth0 에 mac,ip address 추가
ip netns exec pinkns ip link set dev eth0 address 02:42:c0:a8:00:0a
ip netns exec pinkns ip addr add dev eth0 12.12.12.10/24

# node3(skyns) 에서 eth0 에 mac,ip address 추가
ip netns exec skyns ip link set dev eth0 address 02:42:c0:a8:00:0b
ip netns exec skyns ip addr add dev eth0 12.12.12.11/24

# node3(overns) 에서 bridge 생성
ip netns exec overns ip link add dev br0 type bridge
ip netns exec overns ip addr add dev br0 12.12.12.1/24

# node3(overns) 에서 vxlan 생성
ip link add dev vxlan1 netns overns type vxlan id 42 proxy learning dstport 4789

# node3(overns) 에서 veth1 <-> br0, veth2 <-> br0, vxlan1 <-> br0 연결
ip netns exec overns ip link set veth1 master br0
ip netns exec overns ip link set veth2 master br0
ip netns exec overns ip link set vxlan1 master br0

# node3 overns, pinkns, skyns 의 장치들 모두 power on
ip netns exec overns ip link set br0 up
ip netns exec overns ip link set vxlan1 up
ip netns exec overns ip link set veth1 up
ip netns exec overns ip link set veth2 up
ip netns exec pinkns ip link set eth0 up
ip netns exec skyns ip link set eth0 up

# node3(overns) 에 node1,node2 ip,mac 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.3 lladdr 02:42:c0:a8:00:03 dev vxlan1
ip netns exec overns ip neighbor add 12.12.12.2 lladdr 02:42:c0:a8:00:02 dev vxlan1

# node3(overns) 에 node1,nod2 ip,mac 정보를 fdb 로 기록
ip netns exec overns bridge fdb add 02:42:c0:a8:00:02 dev vxlan1 self dst 192.168.104.2 vni 42 port 4789
ip netns exec overns bridge fdb add 02:42:c0:a8:00:03 dev vxlan1 self dst 192.168.104.3 vni 42 port 4789

# node1(overns), node2(overns) 에 node3 ip,mac 정보를 ARP 테이블에 기록
ip netns exec overns ip neighbor add 12.12.12.10 lladdr 02:42:c0:a8:00:0a dev vxlan1
ip netns exec overns ip neighbor add 12.12.12.11 lladdr 02:42:c0:a8:00:0b dev vxlan1

# node1(overns), node2(overns) 에 node3 ip,mac 정보를 fdb 로 기록
ip netns exec overns bridge fdb add 02:42:c0:a8:00:0a dev vxlan1 self dst 192.168.104.4 vni 42 port 4789
ip netns exec overns bridge fdb add 02:42:c0:a8:00:0b dev vxlan1 self dst 192.168.104.4 vni 42 port 4789

# node1(pinkns) -> node3(pinkns), node3(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.10
ip netns exec pinkns ping 12.12.12.11

# node2(pinkns) -> node3(pinkns), node3(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.10
ip netns exec pinkns ping 12.12.12.11

# node3(pinkns) -> node1(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.2

# node3(pinkns) -> node2(skyns) ping 테스트
ip netns exec pinkns ping 12.12.12.3

# 모든 테스트가 끝나고 network namespace 삭제하려면
ip netns delete overns
ip netns delete pinkns
ip netns delete skyns

linux ip iptables 사용하기

# linux 에서 자주 사용되는 ip 명령 예제들
# 참고로 다음과 같이 각 명령에 대한 도움말을 볼 수 있다.
ip addr help 
ip link help 

# 네트워크 장치�ipv4, ipv6 주소 정보
ip addr

# ip 주소할당, dev(device)로 eth0 를 사용
ip addr add 10.10.10.2/24 dev eth0

# ip 주소 삭제
ip addr add 10.10.10.10/24 dev eth0
ip addr delete 10.10.10.10/24 dev eth0

# 장치별 링크 정보 
ip link

# 라우터 정보
ip route

# 연결된 이웃 장치 정보
ip neighbor


##### 네트워크 네임스페이스 구분해서 통신하기 #####


# veth(virtual Ethernet devices) 타입으로
# lemon_eth0 apple_eth0 를 생성하고 연결한다.
ip link add lemon_eth0 type veth peer name apple_eth0

# namespace 확인
ip netns

# LEMON namespace(네트워크가 호스트 네트워크와 격리됨) 생성
# /var/run/netns/LEMON 파일이 생성된다.
ip netns add LEMON
ip netns add APPLE

# lemon_eth0 의 네임스페이스를 LEMON 으로 설정
ip link set lemon_eth0 netns LEMON
ip link set apple_eth0 netns APPLE

# LEMON 네임스페이스에 접속해서 lemon_eth0 장치 시작하기 
ip netns exec LEMON ip link set lemon_eth0 up
ip netns exec APPLE ip link set apple_eth0 up

# LEMON 네임스페이스에 접속해서 lemon_eth0 장치에 ip 설정하기
ip netns exec LEMON ip addr add 10.10.10.2/24 dev lemon_eth0
ip netns exec APPLE ip addr add 10.10.10.3/24 dev apple_eth0

# APPLE apple_eth0 의 패킷을 모니터링 하고
ip netns exec APPLE tcpdump -l -i apple_eth0
# LEMON(lemon_eth0) --> APPLE(apple_eth0) 로 핑을 보내 확인 할 수 있다.
ip netns exec LEMON ping 10.10.10.3

# 참고로 매번 네임스페이스 exec 를 명시하지 않고,
# nsenter 명령으로 네임스페이스 들어가 있을 수 있다.
# 들어간 네임스페이스에 exit 를 하면 빠져나온다.
nsenter --net=/var/run/netns/LEMON
ping 10.10.10.3

# 통신시 ARP 로 매번 브로드캐스팅은 비효율적이라 캐싱하게 된다.
# LEMON 네임스페이스 상에서 이웃을 조회하면 10.10.10.3(apple_eth0)가 캐싱되있다.
ip neighbor

# 현재 네임스페이스를 빠져나온다.(호스트(루트) 네임스페이스로 이동)
exit

# 이제 LEMON, APPLE 네임스페이스 삭제하면 LEMON, BLUE 네임스페이스 안의 이더넷도 모두 삭제된다.
ip netns del LEMON
ip netns del APPLE


##### iptables(netfilter) 설정하기 #####


# iptables 은 커널의 netfilter(프레임워크)에 rules를 설정하고 실제로는 netfilter 로 방화벽 기능이 동작한다.
# netfilter 는 다음 5개의 chain 을 hook 하고 룰에 따라 패킷을 필터링한다.
# PREROUTING: 외부로부터 들어오는 패킷
# INPUT: PREROUTING -> 로컬에서 받아야 하는 패킷
# FORWARD: PREROUTING -> FORWARD -> POSTROUTING 으로 로컬을 거치지 않고 외부로 부터 들어온 패킷을 다른 외부로 가야하는 패킷
# OUTPUT: 로컬 -> POSTROUTING 으로 로컬에서 외부로 가는 패킷
# POSTROUTING: FORWARD 또는 로컬에서 외부로 나가야하는 패킷

# 각 chain 에 맞는 다음과 같은 성격의 룰 테이블이 있다.
# filter:  패킷 필터링에 사용하는 테이블, INTPUT,FORWARD,OUTPUT 에서 사용
# nat: 출발지, 목적지 변경시 사용하는 테이블, PREROUTING,POSTROUTING 에서 사용
# mangle: 패킷 변조시 사용하는 테이블�, 5개 chain 모두에서 사용
# raw: 주로 netfilter 에서 추적하지 않도록 NOTRACK 설정하는데 사용하는 테이블, PREROUTING,OUTPUT 에서 사용
# security: SELinux 보안 사용시 사용하는 테이블, INPUT,FORWARD,OUTPUT 에서 사용

# filter 테이블 -S(list-rules) 룰 리스트 보기
iptables -t filter -S 
# -t 명시하지 않으면 filter 가 기본값이다.
iptables -S

# FOWARD chain에 설정된 rule들 보기 -v(가 없으면 in,out 이더넷 장치가 보인다) 
iptables -L FORWARD -v
iptables -L INPUT -v

# 10.10.10.3 으로 부터 들어오는(INPUT chain) -j(--jump) DROP(패킷 차단) 룰 추가(-A, --append)
iptables -A INPUT -s 10.10.10.3/32 -j DROP

# 10.10.10.3 으로 부터 들어오는(INPUT chain) -j(--jump) ACCEPT(패킷 허용) 룰 추가(-A, --append)
iptables -A INPUT -s 10.10.10.3/32 -j ACCEPT

# 룰 삭제(-D, --delete)
iptables -D INPUT -s 10.10.10.3/32 -j ACCEPT

# -A 같은 내용의 룰이 계속 추가 되 때문에
# -D 같은 내용이라도 마지막 룰만 삭제되어 모두 삭제하려면 N번 실행해야 한다.

# 외부(인터넷) 통신을 위해서는
# POSTROUTING 에 nat 추가
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -j MASQUERADE
# 패킷을 내 사설IP 에서 받을 수 있도록 -d(--destination) 허용
iptables -t filter -A FORWARD -d 10.10.10.3/24 -j ACCEPT

# nat 설정 상태 확인
iptables -t nat -S

네트워크 관련 sysctl

# 연결 지향 tcp 는 데이터를 주고 받기전 우선 연결된다.
# 리슨을 위해 바인딩된 포트 열어 놓는 쪽은 passive open으로 서버가 되고,
# 연결을 요청하는 쪽은 active open으로 클라가 된다.
# tcp 종료 과정은 다음과 같다.
# 그림 출처 : 위키피디아 https://en.wikipedia.org/wiki/Transmission_Control_Protocol


# sysctl 은 런타임시에 커널의 파리미터를 설정하는 명령어다.
# /etc/sysctl.conf 파일로도 설정할 수 있다.
# /proc/sys/net/ipv4 에 파일 수정으로 설정할 수 있다.
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
http://lxr.linux.no/linux+v3.2.8/Documentation/networking/ip-sysctl.txt
# 이중 net.ipv4 로 시작하는 tcp 제어 설정에서 중요한 몇개를 살펴 보자.

# 로컬 포트가 고갈되는 경우
# TIME_WAIT(fin을 받고 서버에 ack 보내고 일정 시간 기다리는 상태)의 소켓들을 재사용할지 여부
# 0 : 비활성화
# 1 : 활성화 (보통 1로 사용)
# 2 : loopback 에서만 활성화
net.ipv4.tcp_tw_reuse = 1

# FIN_WAIT_2(서버쪽 close 중임을 클라에게 알리는 ack 를 받았을때의 클라 상태)이후
# last_ack 를 받지 못했을때 대기시간으로 디폴트 60초이다.
# 참고로 TIME_WAIT 의 타임아웃은 커널소스에 60초로 하드 코딩되어 있다.
# /usr/src/kernels/3.10.0-957.1.3.el7.x86_64.debug/include/net/tcp.h
# #define TCP_TIMEWAIT_LEN (60*HZ)
net.ipv4.tcp_fin_timeout = 60

# 로컬 포트 사용(허용) 범위
net.ipv4.ip_local_port_range = 23768 60999

# tcp_tw_use 처럼 TIME_WAIT 상태의 소켓을 재사용(recycle)할지 여부
# 디폴트는 비활성화
# 여러 문제가 발생될 소지가 있어 최근 리눅스 4.12 에서는 제거되었다고 한다.
https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
net.ipv4.tcp_tw_recycle = 0

Visual C++ test

# SetDIBitsToDevice

# 자신의 ip 주소 얻어오기

# 윈도우의 콘솔 화면에 컬러 텍스트 출력

# 윈도우 전역 메세지 후킹하기