반응형

작성일: 2023년 9월 20일

 

 

 

Client 장비에 network port가 여러개 있는 경우, 특정 network port를 지정하여 IP 패킷을 전송하고 싶을 때가 있다.

이럴 때, source IP address를 binding하면 특정 network port를 통해 IP 패킷이 전송된다.

참고:
  일반적으로 Target IP address로 가기 위한 routing path 및 network port는 
  OS에 있는 Routing table을 통해서 자동으로 결정된다.
  그러나 Target IP address로 가기 위한 routing path가 1개가 아닌 2개 이상인 경우에는
  어느 network port를 통해서 IP 패킷이 나갈지 예측하기 어렵다.  
package main

import (
    "fmt"
    "io/ioutil"
    "net"
    "net/http"
    "time"
)


func main() {
##
## NOTE:  14.33.80.179를 Source IP address로 지정한다. (즉, Source IP address binding)
##
    localAddr, err := net.ResolveIPAddr("ip", "14.33.80.179")
    if err != nil {
        panic(err)
    }

    localTCPAddr := net.TCPAddr{
        IP: localAddr.IP,
    }

    d := net.Dialer{
        LocalAddr: &localTCPAddr,
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
    }

    tr := &http.Transport{
        Proxy:               http.ProxyFromEnvironment,
        Dial:                d.Dial,
        TLSHandshakeTimeout: 10 * time.Second,
    }

    webclient := &http.Client{Transport: tr}

    // Use NewRequest so we can change the UserAgent string in the header
    req, err := http.NewRequest("GET", "https://www.naver.com", nil)
    if err != nil {
        panic(err)
    }

    res, err := webclient.Do(req)
    if err != nil {
        panic(err)
    }

    fmt.Println("DEBUG", res)
    defer res.Body.Close()

    content, err := ioutil.ReadAll(res.Body)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s", string(content))
}

 

 

 

 


 

반응형

 

작성일: 2023년 8월 1일

 

NAVER D2 자료 - TCP/IP Network Stack 이해하기

https://d2.naver.com/helloworld/47667

 

 

 

 

 

 

 

반응형

아래 명령 예시처럼 수행하면, tcp syn과 reset 패킷을 확인할 수 있다.

 

$ tcpdump -i enp1s0 -nN "tcp[tcpflags] == tcp-syn or tcp[tcpflags] == tcp-rst"

16:55:16.516453 IP 65.49.1.10.42458 > 112.169.87.89.87: Flags [S], seq 3730493766, win 65535, length 0
16:55:19.755480 IP 140.99.191.218.57246 > 112.169.89.88.26720: Flags [S], seq 417367123, win 1024, length 0
16:55:19.960898 IP 140.99.191.218.57246 > 112.169.89.88.26720: Flags [R], seq 417367124, win 1200, length 0
16:55:19.991267 IP 185.11.61.225.44794 > 112.169.89.88.38956: Flags [S], seq 163297978, win 1024, length 0
16:55:20.146215 IP 185.11.61.225.44794 > 112.169.89.88.38956: Flags [R], seq 163297979, win 1200, length 0
16:55:38.865833 IP 140.99.191.218.57246 > 112.169.89.88.19331: Flags [S], seq 523253283, win 1024, length 0

 

반응형

Public Cloud의 Kubernetes(예: AWS AKS, Azure AKS, Oracle OKE 등)을 사용하다보면,

Public Network에서 들어오는 UDP 트래픽을 Network LB(NLB)가 처리하지 못하는 것처럼 보일 때가 있다.

 

예를 들어 아래와 같은 Service Manifest를 적용했다고 가정해보자.

 

apiVersion: v1
kind: Service
metadata:
  name: almighty
  annotations:
    oci.oraclecloud.com/load-balancer-type: "nlb"  # <- 이 내용을 추가해야 한다.
spec:
  selector:
    app: almighty
  ports:
    - name: myweb
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: yourweb
      protocol: TCP
      port: 80
      targetPort: 80
    - name: myudp
      protocol: UDP       # <- 테스트를 위해 UDP를 추가한다.
      port: 9090
      targetPort: 9090
  type: LoadBalancer      # <- Service Type을 LoadBalancer로 설정한다.

 

위 Service Manifest를 적용하면, External-IP 항목이 Public IP 값으로 설정되지만 실제로 Pod로 UDP 트래픽이 전달되지 못하는 현상이 생길 것이다.

 

왜 이런 문제가 생길까?

 

Public Network에서 유입되는 UDP 트래픽이 Pod에 전달되지 못하는 정확한 원인은 아래와 같다.

Public Cloud Service 제공사가 제공하는 NLB(Network Load Balancer)는 제대로 UDP 트래픽을 처리한 것이 맞다.

단지, Cloud Infra가 제공하는 K8S Node의 Security Rule에 의해서 UDP 트래픽이 Block되는 것이다.

따라서 Security Rule에 UDP 트래픽이 Pass 되도록 Rule을 추가하기만 하면 된다. (즉, Linux Firewall 설정 하듯이~)

 

AWS AKS, Azure AKS, Oracle OKE 모두 비슷하게 NLB가 UDP 트래픽을 처리하고 Security Rule도 비슷하기 때문에 Oracle의 OCI OKE만 이용해서 설명하면 아래와 같다.

 

아래의 순서로 메뉴/화면을 찾아서 들어간다.

[ Kubernetes Clusters (OKE) ]

-> Clusters 화면에서 특정 Cluster의 VCN을 선택/클릭한다.

-> VCN을 클릭하면, 여러개의 Subnets이 목록이 보여지는데 oke-svclbsubnet-xxxxoke-nodesubnet-yyyy을 선택하여 Security Lists를 확인한다.

-> [ Security Lists ] 화면에 있는 Rule 이름을 선택한다.

-> [ Ingress Rules ]와 [ Egress Rules ] 화면에서 UDP, TCP 트래픽을 모두 허용하도록 Rule을 추가한다.

     예를 들어, 115.33.55.0/24, 특정 UDP 포트(예: 9090), 특정 TCP 포트(예: 8080) 허용으로 설정하면 된다.

 

아래 화면을 참고~~~

 

 

 

이렇게 Security Rule을 추가하고, 다시 Public IP와 UDP 포트를 이용하여 트래픽을 보내보면, Pod 내부까지 UDP 트래픽이 잘 전달되는 것을 확인할 수 있다.

 

 


조심해야 할 사항:
  Security Rule 설정하고, 40초 후에 Traffic Test해야 한다.
  Node Security Rule이 적용되기 까지 40초가 걸리기 때문에 그 이후에 Traffic Test를 해야 제대로 Traffic이 Pod까지 전달된다.
  

 


생각해볼 내용:
  Node Security List에 TCP Rule을 추가할 때, 왜 Egress Rule도 추가해야 하는지 잘 이해가 안 된다.
  Cluster 외부에서 Ingress Rule에 따라 TCP Traffic을 허용해주면, ConnTrack DB에 Pin Hole 같은게 생기면서
  TCP의 응답 패킷도 알아서 Pass(Forward)시켜주는게 일반적인 Traffic 처리가 아닐까라고 생각했는데... 이게 아닌가 보다.
  아무튼 귀찮지만 Ingress에 추가한 Rule을 Egress에도 꼭 추가해야 한다. (잊지 말자 !!!)

 

 

 

 

참고하면 좋은 Web Docs

Oracle OCI Network Load Balancer 사용하기

https://thekoguryo.github.io/release-notes/20220315-support-for-oci-network-load-balancers/

 

Support for OCI Network Load Balancers

OKE에서 Service Type을 Load Balancer를 사용할때 이제는 OCI Network Load Balancer을 추가적으로 지원합니다.

thekoguryo.github.io

 

위 문서는 간단하게 사용법 위주로 설명되어 있고, 아래 문서는 내부 동작에 관해 자세하게 내용을 다루고 있다.

특히, Service Manifest의 externalTrafficPolicy: local 방식에 관해 궁금하다면 아래 문서를 보는 것이 좋다.

 

https://blogs.oracle.com/cloud-infrastructure/post/network-load-balancer-support-on-oracle-kubernetes-engine

 

Using a network load balancer for Kubernetes services

Announcing network load balancer support on Oracle Container Engine for Kubernetes.

orasites-prodapp.cec.ocp.oraclecloud.com

 

더 자세히 파고 들어가고 싶다면, Oracle 공식 Web Docs를 보길~~~

 

https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengcreatingloadbalancer.htm

 

Defining Kubernetes Services of Type LoadBalancer

Include in the backend set:

docs.oracle.com

 

반응형

 

Netcat(nc) TCP, UDP를 통해 Peer(Client/Server) 연결하고, 데이터를 읽고 쓰는 유틸리티 프로그램이다.

 

대부분 개발자, 운영자가 아래와 같은 목적으로 NC 명령을 사용할 것이다.

 

1)  두 장비(Network Node) 간에 IP Network이 정상인지 확인하거나

2)  중간에 방화벽이 있다면, 방화벽 정책이 적용되었는지 직접 TCP, UDP 트래픽을 테스트하기 위해서 NC를 사용한다.

3)  서버 또는 클라이언트 한쪽만 개발(구현)한 뒤에 Peer를 시뮬레이션하기 위해서...  (즉, 시뮬레이터 만들기 귀찮아서 ㅋㅋ) 

 

 

 

설치

 

##
## Mac OS 에 설치하는 경우
##

$  brew install netcat


##
## Ubuntu 에 설치하는 경우
##

$  apt install -y netcat


##
## CentOS, Redhat 에 설치하는 경우
##

$  yum install -y nc

 

 

 

사용 방법 / 예제

 

장황하게 설명하는 것보다는 아래 화면 캡처 하나가 훨씬 이해하기 좋을 듯~~~

그냥 아래 화면처럼 따라하면 테스트가 잘 된다.

 

##
## Netcat Server
##

$  nc  -l  -p 9090


##
## Netcat Client
##

$  nc  10.10.5.3  9090

이것은 테스트 메시지이다. (enter key)
...
...
... 이런 식으로 메시지를 타이핑하면서 테스트한다 ...
...
...

^C

$

 

 

게시물 작성자: sejong.jeonjo@gmail.com

 

반응형

tcpdump 명령만 이용하면, 출력을 보기 좋게 또는 예쁘게 터미널로 출력하기 어렵다.

보기 좋은 형식으로 출력하려면 tshark 명령을 사용하는 것을 추천한다.

 

 

tshark 명령 사용

tshark을 사용하면, Network Packet이 정말 예쁘게 출력된다.  

아래와 같이 wireshark 패키지를 설치한다.  (참고로 tshark은 wireshark 패키지에 포함되어 있다)

##
## 아래 예시처럼 yum install 명령을 이용하여 wireshark 패키지를 설치한다.
##

$ yum install wireshark
...

##
## 설치 완료 후, 아래 명령과 같이 실행
## 참고: -V 옵션은 Packet을 Decode해서 출력하라는 뜻
##
$ tshark -i eth0 -nV port 53

 

위 예제 명령 정도의 옵션만 사용해도 꽤 보기 좋은 모양으로 IP 네트워크 패킷이 출력된다.

 

 

tcpdump 명령의 -A 옵션 사용해서 가독성 높게 출력하기

tshark을 사용할 수 없는 경우라면, 아래 명령처럼 -A 옵션을 주면, TCP 또는 UDP의 Payload가 ASCII 로 출력된다.

(사람 눈으로 읽을 수 있는, 즉 Readable Character만 터미널에 출력함) 

 

-A 옵션만 사용하면, TCP 세션을 수립하기 위한 SYNACKFIN 패킷도 모두 보여지기 때문에 

Filter에  tcp[32:4] = 0x47455420 조건을 추가한다. ("GET "에 대한 Pointcode 값이다) 

 

 

HTTP GET 요청 메시지만 출력
$ tcpdump -i p2p2 -s 1500 -An 'src net 192.168.0.0/24' and dst port 80 and 'tcp[32:4] = 0x47455420'

 

 

HTTP GET 요청과 응답 메시지 모두 출력
$ tcpdump -i em2 -s 1500 -An 'src net 192.168.0.0/24' and 'tcp[32:4] = 0x48545450' or 'tcp[32:4] = 0x47455420'

 

  또는 아래와 같은 방식을 사용할 수 있다.

(이 방식을 추천함)

$ tcpdump -i em2 -An -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

 


참고: 위의 3개 명령 중에서 제일 마지막 명령이 제일 출력 포맷이 예쁘다. 

+ Recent posts