Terraform 오버뷰 - GCP Cloud Run 배포하기 공부/CLOUD

Date 2021. 8. 16. 16:29

테라폼이란

클라우드의 인프라를 선언적(declaritve)으로 관리할 수 있게 해주는 IaC(Infrastructur as Code) 오픈소스 소프트웨어이다.

 

다시 풀어서 말하면 클라우드의 리소스(EC2의 경우 ami, instance type, GCP Cloud Run의 경우 컨테이너의 spec 등..)을

1) 선언적 2) 소스코드로 관리 할수 있는 소프트웨어라 할 수 있다.

 

이러한 IaC 툴을 이용하면 기존에 리소스를 CLI/ 콘솔 등으로 관리할때 보다 다양한 장점을 가져갈 수 있다.

 

1) 기존 방식인 콘솔 또는 CLI(API call) 을 통해 클라우드 리소스에 접근하는거와 달리 Code로 관리함으로써 클라우드 인프라에 대한 버전관리를 할 수 있다.(git 등 이용)

2) 코드로 관리하기 때문에 같은 인프라를 여러번 복제 하는 등 쉽게 인프라를 배포할 수 있다.

 

리소스 배포하기

가장 먼저 클라우드 리소스에 접근할 수 있는 API Key가 필요하다. GCP를 사용했고 json 형식의 키를 발급받아 사용했다.

1) Configuration

우선 테라폼 CLI를 설치해야 한다. 단일 바이너리 파일로 설치되므로 편리하다.

 

sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

sudo apt-get update && sudo apt-get install terraform

 

다음은 테라폼에 대한 Configuration을 해주어야 한다. 폴더를 생성하고 key file을 가져온 뒤 main.tf를 수정한다.

 

cd terraform
cp JSON_KEY ./key.json

vi main.tf

terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
      version = "3.5.0"
    }
  }
}

provider "google" {
  credentials = file("key.json")

  project = "PROJECT"
  region  = "REGION"
  zone    = "ZONE"
}

GCP를 기준으로 했으며 PROJECT, REGION, ZONE을 적절히 입력한다.

 

이제 테라폼 CLI를 이용해 프로젝트를 초기화한다.

 

terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/google from the dependency lock file
- Installing hashicorp/google v3.5.0...
- Installed hashicorp/google v3.5.0 (signed by HashiCorp)

 

2) Write

이제 배포할 리소스에 대한 선언이 필요하다. 간단한 Cloud Run 컨테이너를 배포한다.

 

vi cloudrun.tf

resource "google_cloud_run_service" "default" {
  name     = "cloudrun-srv"
  location = "asia-northeast1"

  template {
    spec {
      containers {
        image = "us-docker.pkg.dev/cloudrun/container/hello"
      }
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }
}

 

Terraform Registry 에서 배포 가능한 리소스들의 정보를 알 수 있다.

 

3) Apply

terraform apply를 통해 기존 state와 리소스들을 비교하며 업데이트를 수행한다.

 

terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

...

 

4) 결과 확인

 

terraform show 명령어는 현재 state를 보여준다. 

 

terraform show

resource "google_cloud_run_service" ...

terraform show | grep url

url = "https://cloudrun-srv-ㅁㅁ-an.a.run.app"

// 컨테이너 cold start로 응답 지연될 수 있음
// IAM Policy를 설정해주지 않아 Forbidden을 반환합니다.
curl https://cloudrun-srv-ㅁㅁ-an.a.run.app
...

 

쓰면서 느낀 점

일단 쉽게 리소스를 배포할 수 있다는 뚜렷한 장점이 있다. 또한 테라폼 공식 페이지가 굉장히 잘나와있고 레퍼런스가 많아 참고할 자료가 많다.

 

반면에 불편한 점들도 존재한다.

기존에 있던 리소스를 테라폼으로 관리하기 위해서는 terraform import 를 통해 불러와야 하는데,

 

state만 업데이트 하고 configuration은 관리해주지 않는다. 손으로 한땀한땀 tf 파일을 수정해줘야 한다.

이를 위해 terraforming이나 terraformer 등의 도구가 존재하지만 완벽하지는 않아서 직접 수정해야 할 필요가 있다.

 

또한 테라폼 자체의 단점은 아니지만 테라폼으로 생성한 리소스를 기존 방식인 CLI등으로 수정하면 당연히 state와 어긋나게 된다. 이를 맞추려면 terraform taint나 terraform apply -replace를 통해 state를 맞춰줘야 할 필요가 있다.

[k8s] Service 리소스 Overview (2) : Ingress와 Health check 공부/CLOUD

Date 2021. 8. 15. 17:34

저번 글에 이어 Ingress와 Health check를 정리했다.

Ingress

  • 쿠버네티스 Ingress 리소스를 통해 HTTP 트래픽을 여러 Service 로 전달할 수 있다.
  • 우선 실제로 트래픽을 보고 처리해야 하는 Ingress Controller 가 필요하다. 대표적으로 오픈소스 웹서버인 nginx 구현체인 Nginx Ingress Controller 가 존재한다.
  • https://kubernetes.io/ko/docs/concepts/services-networking/ingress-controllers/
    • 구글의 쿠버네티스 서비스인 GKE 는 자체적으로 구현한 ingress-gce 가 존재한다.
  • 접근하는 트래픽에 대해 어떻게 처리할지에 대해서 관리하는게 Ingress 리소스이다.
 

인그레스 컨트롤러

인그레스 리소스가 작동하려면, 클러스터는 실행 중인 인그레스 컨트롤러가 반드시 필요하다. kube-controller-manager 바이너리의 일부로 실행되는 컨트롤러의 다른 타입과 달리 인그레스 컨트롤러

kubernetes.io

 

  • metadataannotations 를 이용해 인그레스 오브젝트에 대한 옵션을 설정할 수 있다.
    • nginx 의 경우 nginx.ingress.kubernetes.io/rewrite-target 같은 옵션이 존재한다.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  annotations:
  ...
spec:
  rules:
    - host: test.example.com
    http:
        paths:
        - path: /test
            backend:
                service:
                    name: test
                    port:
                        number: 80

 

  • Ingress 리소스의 경우 Ingress Controller 가 받는 트래픽 중
    • 요청의 Host 헤더가 test.example.com 인 요청에 대해 test 서비스의 80 포트로 보내진다.
  • 하나의 Ingress 에 다양한 rulespath 를 사용할 수 있다.
    • GCP 에서 사용하는 Cloud Load Balacerurl map 이란 리소스가 해당 역할을 담당한다.
      • ingress-gce 레포에 pkg/loadbalancer/url_maps 로 확인할 수 있다.

Ingress TLS

  • Ingress Controller 는 HTTPS 트래픽을 받아 TLS Connection 을 열고 백엔드에 위치한 서비스들에는 HTTP 트래픽으로 전송한다.(Terminate TLS)
  • TLS 연결에 사용되는 서버 인증서는 발급받은 뒤 Secret 리소스를 사용하여 저장할 수 있다.
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj \
CN=test.example.com

kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key

 

  • 또는 CSR 을 생성해서 CertificateSigningRequest 리소스를 통해 발급받아도 된다고 한다.
kind: Ingress
...
spec:
    tls:
    - hosts: 
        - test.example.com
        secretName: tls-secret
...

 

annotationnginx.gress.kubernetes.io/ssl-redirect 기본값은 True 다. 즉 HTTP 로 요청을 보내도 tls 가 존재하면 HTTPS 로 리다이렉트한다.

Health check

  • ServicelabelSelector 에 맞는 Pod 들은 자동으로 서비스의 Endpoint 리소스로 등록된다. 하지만 Pod 가 생성된 뒤 Configuration이 필요하거나 등의 warm-up 절차가 있다면 Service 는 해당 Pod 로 요청을 보내서는 안될것이다. 이를 위해 Readiness Probe가 존재한다.

Readiness Probes

  • Pod 가 클라이언트의 요청을 받아들일 수 있는지 확인하기 위해 존재한다.
  • 주기적으로 호출되어 Pod 가 요청을 받을 수 있는지 확인한다.
  • Container 마다 요청을 받을 수 있다는 상태는 다르다. 쿠버네티스는 3가지 종류를 지원한다.
    • HTTP GET probe : 요청을 보내 HTTP Status code를 보고 확인한다.
    • TCP Socket : 컨테이너의 특정 port로 소켓을 오픈한다. Established 면 Ready 상태.
    • Exec probe : 컨테이너에서 프로세스를 실행해 Exit status code를 참조한다.
  • Liveness Probe 와 달리 실패해도 Pod를 재시작하지는 않는다.

[k8s] Service 리소스 Overview (1) 공부/CLOUD

Date 2021. 8. 14. 19:26

클러스터 내부에서든 외부에서든 실제 Workload를 받는 부분인 Pod에 접근하기 위해서는 Pod의 IP정보+ port를 알아야 한다.

 

Replication Controller가 조정할 수도 있고 Node가 죽어서 다른 Node 로 파드를 옮기는 등 쿠버네티스에서 Pod라는 리소스는 항상 죽을 수 있다. 즉 Pod를 식별하는 IP는 계속 변경된다.

 

이런 문제를 해결하기 위해서 Pod에 접근하는 고정된 IP가 필요한데, 이를 담당하는 오브젝트가 바로 Service 이다.

 

서비스는 리소스가 살아있는 한 고정된 IP를 가지고 있으며, TCP/UDP 패킷을 Pod로 Redirect 해준다.

Service의 작동방식

우선 어떤 Pod로 트래픽을 분산할지 Pod를 찾아야 한다. Pod를 찾는 방법은 labelSelector가 있다. (다른 방법이 있을 수 있음~?)

 

우선 해당 Selector를 만족하는 Pod들을 찾는다. 또한 그 Pod의 IP를 이용해 Endpoint 리소스(IP:ContainerPort)를 생성한다.

 

EndPoint 리소스들은 서비스에 붙게되며, 클러스터 내부의 클라이언트가 해당 서비스에 요청을 보내면 서비스는 해당하는 Endpoint 중 하나로 트래픽을 redirect 하게 된다.

 

  • 만약 Pod가 요청에 대한 세션을 가지고 있어야 한다면 sessionAffinity 를 사용할 수 있다. 이를 통해 요청은 계속해서 동일한 Pod로 전달된다.
  • Service는 TCP/UDP 트래픽을 분산하므로 HTTP 메시지를 볼 수 없다. ( 따라서 Cookie 값을 보고 로드밸런싱 한다던지의 기능을 수행할 수 없다. )
  • 여러개의 Port를 서비스에 연결할 수 있다.
  • targetPort로 숫자 이외의 http,https 등 alias 등을 사용할 수 있다. 이렇게 사용하면 Pod의 포트가 변경되어도 서비스를 수정할 필요가 없다.

Discovering Service

클러스터 내부에서 Service로 요청을 보내려면 해당 Service의 IP를 알아야 한다. 어떻게 알아야 할까?

  1. ENV
    1. 파드가 실행되면 환경변수 값들로 서비스의 IP와 포트가 들어간다. 가장 처음 존재하는 쿠버네티스 서비스의 경우
KUBERNETES_SERVICE_HOST= ... 
KUBERNETES_SERVICE_PORT= ...

로 파드 컨테이너의 환경변수로 들어간다.

 

  1. DNS
    1. 내부 DNS 서버인 kube-dns를 이용한다. 해당 DNS 서버에 서비스의 FQDN을 쿼리함으로써 서비스의 IP를 찾을 수 있다.

Service outside the cluster

Pod가 클러스터 외부 리소스에 접근할 때도 Service 리소스를 사용할 수 있다. externalName 타입의 서비스로 클러스터 외부의 도메인을 등록함으로써 서비스의 FQDN을 통해 클러스터 외부의 서비스에 접근할 수 있다.

 

Service를 클러스터 외부에 노출하기

 

클러스터 외부의 클라이언트가 Service에 요청을 보내기 위해서는 다양한 방식이 존재한다.

 

  1. NodePort
    1. 말 그대로 (워커)Node의 Port를 오픈한다. 해당 NodeIP:Port로 요청을 보내면 NodePort서비스는 Pod로 트래픽을 redirect 한다.
    2. 서비스에 dedicated한 Node의 Port를 할당한다. 해당 서비스로 트래픽을 보내려면 두가지 방법이 존재한다. 
    3. SERVICE_IP:PORT, nth NODE IP:NODEPORT
    4. SERVICE_IP의 경우 클러스터 내부 IP이고, 클러스터 외부에서는 NODE의 IP를 통해 접근할 수 있다.(물론 인바운드 NODEPORT에 대한 트래픽을 받아야 한다.)
    5. 이 방법의 경우 특정 노드가 죽어버리면 그 IP를 통해서는 더이상 트래픽을 받지 못한다는 단점이 있다.
  1. LoadBalancer
    1. Kubernetes Cloud Provider들이 제공해주는 LoadBalancer 리소스를 통해 dedicated IP로 트래픽을 받아 NodePort로 트래픽을 redirect한다.
    2. public하게 접근가능한 IP를 할당한다. 내부적으로는 NodePort서비스로 구현된다.
    3. LB의 IP:PORT로 접근 시 특정 NodePort로 연결한다. 해당 NodePort는 또 Pod로 트래픽을 분산한다.(implicitly assigned Nodeport)
  1. Ingress
  • 주로 HTTP 패킷을 받아 여러 서비스로 패킷을 전달한다. (다음 글에서 설명)

 

Peculiarities of External Connection

  1. 불필요한 Network hops
    1. 외부에서 Pod로 트래픽을 보내려면 LB -> NodePort -> Pod를 거친다. 여기서 Node에 Pod가 존재할 수도 있고 없으면 다른 Node로 보낼 수도 있는데, 이는 불필요한 hop수를 증가시킨다.
    2. Service 오브젝트의 스펙에 externalTrafficPolicy: local 을 명시하면 해당 Node에 존재하는 파드로만 트래픽을 분산한다. ( 이 경우 해당 Node에 실행중인 Pod가 없다면 hanging된다. 또한 트래픽을 불균등하게 받을 수 있다.. 특정 Node에 실행중인 Pod가 많으면)

 

  1. Client IP를 잃어버린다.
    1. Nodeport 서비스의 경우 SNAT해서 원래의 IP를 잃어버리고 Pod에 트래픽이 도달한다.

 

References

Service, Kubernetes up & running

JWT(Json Web Token)이란 공부/BE, DB

Date 2021. 7. 30. 14:52

JWT란 서비스와 서비스 간 통신 시 인증(Authentication)과 인가(Authorization)에 주로 사용하는 토큰이다.

 

요청을 하는 서비스는 JWT를 포함하여 요청을 전송하고, 요청을 받아들이는 서버는 이 JWT를 보고 해당 요청을 허가하거나 거부한다.(Authorization)

 

JWT RFC문서를 살펴보면(rfc7519) 'The JWT conform to either the JWS or JWE specification' 이라고 적혀있다.

즉 JWS 또는 JWE Spec을 구현한 것이 JWT라고 할 수 있다.

 

여기서 우리가 살펴볼 것은 대부분 JWT 구현에 사용하는 Header, Payload, Signature로 구성되는 JWS Specification이다.

 

JWS로 구현한 JWT의 정의를 살펴보자면,

1. URL-safe 하다. 즉 HTTP Request에 JWT를 포함할 시 요청의 URL(path) 부분에도 넣어도 상관이 없다는 뜻이다.

2. 총 3개의 부분 : Header, Payload, Signature로 구성되고, 각 세 부분을 '.'로 구분한다.

3. Header와 Payload는 JSON 객체를 BASE64url 인코딩한 문자열이다.

4. key:value 쌍을 claim이라 하고 a set of claims를 JSON 객체로 표현한다.

 

 

JWT 생성하기, JWT 검증하기, JWT 사용 사례 크게 세 부분으로 나누어 설명하겠다.

JWT 생성하기

Payload

일단 정보를 담을 Payload를 만들어야 한다. 이 Payload는 a set of claims을 JSON 형태로 나타낸 뒤 URL-safe 하게 BASE64url 인코딩 한 것이다.

claim의 key는 string이어야 하고 value는 JSON value여야 한다. 이 조건을 만족시키면 claim이 될 수 있다.

 

IANA(Internet Assigned Numbers Authority)에 가면 자주 사용하는 payload claim들이 나열되어 있다.

 

대표적으로 iss(issuer), sub(subject), exp(expiration) 등이 존재한다. 이외에도 필요한 정보를 Payload에 claim 형태로 담을 수 있다.

{
  "iss": "donghyeong",
  "sub": "intro"
}

 

위와 같은 JSON을 BASE64url 인코딩하면 Payload가 완성된다.

 

ewogICJpc3MiOiAiZG9uZ2h5ZW9uZyIsCgkic3ViIjogImludHJvIgp9

Header

 

헤더는 JOSE(JSON Object Signing and Encryption) 헤더라고 한다. 즉 이 JWT 토큰이 무결(integrity)한지 확인하기 위한 메타데이터들을 담고 있다. 자세한 정보는 마찬가지로 IANA 에서 확인할 수 있다.

 

가장 중요한 claim은 alg로, 나중에 Signature를 생성하고 검증할 때 사용한다. 자세한 내용은 뒷부분에서 설명하겠다.

 

{
  "alg": "HS256"
}

 

마찬가지로 위와 같은 JSON을 BASE64url 인코딩하면 Header가 완성된다.

 

eyJhbGciOiJIUzI1NiJ9

Signature

 

JWT의 Header와 Payload는 단순히 BASE64url 인코딩한 것이기 때문에 누구나 읽거나 수정할 수 있다. 이러한 정보들이 변조되지 않았음을 증명하기 위해 서명(Signature)를 이용한다.

 

Header와 Payload를 이어붙인 값에 헤더의 알고리즘을 이용해 서명(Signature) 한다.

 

SIGNATURE = BASE64url(ALGORITHM(Header + '.' + Payload, Private Key))

 

이러한 서명 알고리즘에는 대표적으로 SHA등 HMAC으로 대표되는 대칭키 알고리즘,

비대칭키를 사용하는 알고리즘 등이 존재한다.

 

"구글 계정으로 로그인" 등 OpenID Connect에서는 비대칭키를 사용하는 JWT를 사용한다고 한다.

구글같은 ID-Provider는 구글의 Private key로 토큰을 서명하고, "구글 계정으로 로그인" 등 기능을 사용하는 App은 구글의 Public key로 해당 토큰을 검증하여 Integrity를 확인한다.

 

본론으로 돌아와 이렇게 생성된 Signature를 Header와 Payload에 이어붙이면 JWT가 완성된다.

 

JWT = HEADER.PAYLOAD.SIGNATURE

JWT 검증하기

 

이렇게 생성된 JWT가 변조되지 않았음을 확인하기 위해서는 Signature를 이용해 검증하게 된다.

Key(비대칭 알고리즘의 경우 Public Key)를 알고 있다고 가정하고 Header와 Payload의 값을 헤더의 알고리즘으로 계산한 결과가 Signature와 같으면 Validate하다고 판단한다.

 

ALGORITHM(HEADER + '.' + PAYLOAD, Key) === BASE64urlDecode(SIGNATURE)

JWT 사용 사례

API Key

JWT를 API Key로 사용해 클라이언트는 JWT를 포함하여 요청하고, 서버는 해당 JWT를 보고 해당 요청을 받아들일지 거부할지 선택한다.

  1. 클라이언트는 서버에게 JWT를 제공받는다. ( 로그인 등 )
  2. API Call시 HTTP 요청에 JWT를 담아 ( 보통 Authorization Header ) 전송한다.
  3. 서버는 해당 JWT를 검증하고 Payload에 담은 값을 바탕으로 API요청을 처리하거나 거부한다.

OAuth

인증/인가 관련 표준인 OAuth2.0에서도 토큰으로 JWT를 사용할 수 있다.

 

 

 

[Network] HTTPS와 TLS Computer Science/Network

Date 2021. 6. 23. 16:00

HTTP(Hypertext Transfer Protocol)은 이름에서도 알 수 있듯이 text를 전송하는 프로토콜이다.

 

최근에는 text 뿐만 아니라 정말 다양한 정보들이 HTTP 프로토콜을 이용하여 주고 받아진다. 

 

또한 동시에 HTTP 위에서 민감한 정보를 전송하는 수요도 증가하기 시작했는데, 

 

보안이 요구되기 시작함에 따라 SSL(Secure Socket Layer)같은 프로토콜이 디자인되었다.

 

HTTPS는 이러한 보안 레이어 위에서 HTTP를 이용하는 구조로, 따라서 HTTP에 담긴 평문 데이터를 암호화해서 주고받을 수 있다.

 

 

1. HTTP Over TLS

RFC2818은 HTTP Over TLS란 이름으로 말 그대로 TLS 레이어 위에서 HTTP를 전송하는지에 대해 담고 있다.

 

여기서 중요한 하위 레이어인 TLS은 두 가지 역할을 수행한다.

 

1. End Host 간 안전한 데이터 전송 및 무결성 확인

2. 인증서를 통해 통신 상대가 신뢰할 수 있는지 확인

 

데이터를 암호화하여 전송하고, 받는 측에서는 데이터를 복호화하여 HMAC 알고리즘을 이용해 무결성을 검증한다.

 

또한 통신 시작 전 상대의 Certificate(보통 서버의 Certificate)를 받아 통신 상대가 신뢰가능한지 검증한다.

 

2. TLS

위에서 말했던 2가지 역할은 모두 TLS Handshake로 부터 시작된다.

 

이 Handshake를 통해 서버와 클라이언트는 Cipher Suite라는 구조체를 정의하게 되고,

이 구조체를 이용하여 통신에 사용할 암호화 관련 알고리즘을 정의한다.

 

또한 Handshake 과정을 통해 인증서를 전송하고, 암호화에 사용할 Symmetric 키를 정의한다.

 

이제 Handshake 과정을 자세히 알아보자.

 

RFC 5246 : TLS Handshake

 

클라이언트-서버 구조로 먼저 처음엔 Client가 TLS 세션을 시작하는 ClientHello 메시지를 보내며 시작된다.

 

1) ClientHello

 

이 단계에서는 클라이언트가 사용 가능한 Cipher Suite 리스트와, 기타 메타데이터들을 전송하게 된다.

메타데이터 중 Session ID는 서버가 클라이언트 정보를 식별해, 최근에 연결되었던 세션이면 서버와 클라이언트는 이후 과정을 생략하여 Handshake를 끝내고 기존 Cipher Suite와 비밀키를 이용해 연결을 시작한다.

 

Wireshark : 서버에 보낸 Cipher Suite 리스트

 

2) ServerHello

 

ClientHello를 받은 서버는 ServerHello 메시지로 클라이언트에 응답하게 된다.

이 메시지에는 클라이언트가 보낸 Cipher Suite 리스트 중 하나가 포함되고, 이 Cipher Suite를 이용하여 암호화를 진행한다

 

WireShark : Cipher Suite 선택 후 전송

 

여기서 서버는 Cipher Suite로 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 을 선택했는데, 이는

 

1. 대칭키 교환 방식은 ECDHE( Elliptic-Curve 디피헬만)

2. 인증서 서명 방식 RSA

3. 대칭키 암호화 알고리즘 AES128_GCM (Galois/Counter Mode)

4. HMAC 알고리즘 SHA256

 

을 사용한다는 의미이다.

 

3) Certificate

서버는 ServerHello 이외에도 여러 메시지를 전송하게 되는데, 첫번째로 Certificate이다.

 

이 Certificate에는 Root CA의 인증서부터 서버의 인증서까지 Certificate chains을 전송하게 된다.

 

필요에 따라 서버가 클라이언트의 신원이 필요할 경우 CertificateRequest를 클라이언트에 전송해

클라이언트 또한 서버에게 Certificate 메시지를 전송할 수 있다.

 

이 과정을 통해서 상대방의 서명된 인증서를 받고 이를 검증함으로써 통신상대가 신뢰할 수 있는지 검증하게 된다.

 

다음 링크에서는 Certificate chain 과정에 대해 자세히 설명해주고 있다.

https://support.dnsimple.com/articles/what-is-ssl-certificate-chain

 

What is the SSL Certificate Chain? - DNSimple Help

What is the SSL Certificate Chain? There are two types of certificate authorities (CAs): root CAs and intermediate CAs. For an SSL certificate to be trusted, that certificate must have been issued by a CA that’s included in the trusted store of the devic

support.dnsimple.com

 

4) ServerKeyExchange

Diffie Hellman을 키 교환 알고리즘을 사용할 경우 KeyExchange 과정을 통해 암호화에 사용할 키를 생성하기 위한 데이터를 주고받는다.

 

서버는 ServerKeyExchange, 클라이언트는 ClientKeyExchange 메시지를 통해 데이터들을 주고받는다.

 

5) ServerHelloDone

ServerHello 부터 시작해 필요한 메시지들을 모두 전송하면 서버는 ServerHelloDone을 통해 보낼 메시지는 다 보냈다고 알린다.

6) ChangeCipherSpec

데이터 전송 및 검증에 필요한 모든 데이터를 교환하고 암호화에 사용할 비밀키를 생성했다면 서버와 클라이언트는 각각 ChangeCipherSpec 메시지를 통해 이제 다음부터 보낼 데이터는 암호화 해서 보내겠다고 알린다.

 

7) Finished

Handshake 과정을 종료하고 이젠 Application Data를 암호화하여 전송하고, 받는 측에서는 복호화하여 무결성을 검증한다.

 

 

3. 참고

 

 

https://luavis.me/server/tls-101

https://rsec.kr/?p=455

 

'Computer Science > Network' 카테고리의 다른 글

[Network] DNS(Domain Name System) 란 무엇일까  (0) 2021.05.29

[Network] DNS(Domain Name System) 란 무엇일까 Computer Science/Network

Date 2021. 5. 29. 20:21

1. Domain ? 

 

웹브라우저를 통해 네이버를 접속하기 위해서 우리는 naver.com 이란 도메인을 이용한다. 하지만 웹 브라우저가 서버와 통신하기 위해서는 naver.com 가 아닌 서버의 IP 주소를 알아야 하는데 이 때 도메인을 IP 주소로 변환하는데 도움을 주는 것이 DNS 이다. 이렇게 도메인을 IP로 변환한 이후에 웹브라우저는 본격적으로 서버에 요청을 보내게 된다.

 

2. DNS 질의

 

DNS 정보를 알기 위해 클라이언트는 DNS 질의(DNS Query)를 서버에 보내게 된다. 

이 때 매번 DNS 서버에 질의를 할 수 없으므로 브라우저와 운영체제는 DNS 레코드 정보를 캐싱하게 된다. 만약 도메인 정보가 캐싱되어 있으면 그대로 변환하고, 없으면 이제 IP를 얻기 위한 DNS Query가 시작된다.

 

먼저 가장 먼저 로컬에 등록된 DNS Resolver로 쿼리를 보낸다. DNS Resolver는 클라이언트에게 적절한 응답을 할 책임이 있다. 

먼저 DNS Resolver는 클라이언트의 쿼리를 받고 자신의 캐시를 확인한다. 이 때 캐싱되어 있으면 응답하고,

아니면 루트 네임 서버에 쿼리한다. 루트 네임 서버는 전 세계에 13대 밖에 없다고 한다.

 

루트 네임 서버는 쿼리를 받고 여기서 TLD(Top-Level-Domain) 서버의 주소를 응답한다.  naver.com 의 경우 TLD는 com 으로, 루트 네임 서버는 .com DNS 서버의 주소를 응답해 준다.

 

이제 DNS Resolver는 TLD DNS 서버에 Query를 보내고, TLD DNS 서버도 마찬가지로 캐싱되어 있으면 응답하고, 그렇지 않다면 해당 도메인의 네임서버의 주소를 응답해주게 된다. 

 

마지막으로 해당 도메인의 네임서버는 DNS 레코드를 갖고 있으며, DNS Resolver -> Client 순으로 응답하게 된다.

 

DNS Query를 빨리 해결하기 위해서 서버들은 다양한 정보를 캐싱해둔다. 이 때 DNS 레코드의 TTL(Time-To-Live)란 캐싱된 정보가 유효한 시간으로 이 시간 동안은 캐싱을 유지한다.

 

 

References

 

https://www.cloudflare.com/ko-kr/learning/dns/what-is-dns/

 

'Computer Science > Network' 카테고리의 다른 글

[Network] HTTPS와 TLS  (0) 2021.06.23

[Container] Container와 VM 공부/OTHERS

Date 2021. 5. 27. 16:23

두 기술 모두 프로그램을 독립적으로 실행하기 위해 사용한다. 이는 하드웨어 자원을 효율적으로 쓸 수 있게 해준다.

VM

VM(Virtual Machine) 은 Hypervisor 라는 소프트웨어 위에서 관리된다.
Hypervisor가 호스트와 VM 사이에서 중간 관리자 역할을 하며 VM을 생성 및 관리하고 시스템 콜등을 실행한다.
이 때 Hypervisor 위에서 돌아가는 OS를 Guest OS라 하며 Guest OS > Hypervisor >( Host OS ) > Hardware 구조로 구성되게 된다.

 

크게 Type1과 Type2가 있는데,

Type1 Hypervisor는 Native 방식이라 하여 하드웨어 위에서 바로 실행되며 하이퍼바이저가 바로 하드웨어를 제어하게 된다. 직접 하드웨어를 제어하므로 Type2에 비해 오버헤드가 적다. 대표적으로 Xen, 리눅스의 KVM 등이 존재한다.

 

Type2 Hypervisor는 호스트 하이퍼바이저라고 불리며 하드웨어 -> Host OS -> Hypervisor 구조로 구성되어 중간 다리 역할을 해준다. 하드웨어 리소스에 접근하기 위해 Host OS에 요청해야 하므로 오버헤드가 있다.

 

AWS EC2는 Xen Hypervisor 와 AWS Nitro Hypervisor를  사용한다고 한다. 

Container

상대적으로 가벼운 가상화 방법으로, 같은 호스트 위에서 프로세스를 격리한다.
호스트 위에서 커널을 공유하므로 거의 0에 가까운 오버헤드를 가지며 프로세스를 격리된 환경에서 실행할 수 있게 해준다.

 

이는 리눅스 커널에 내장된 namespacecgroups 기능을 이용해서 구현될 수 있다.

 

먼저 namespace는 호스트에서 독립된 제한된 공간을 할당해주는 기능으로,

총 6개의 네임스페이스( mount, pid, network, ipc, uts, uid) 가 존재한다.

 

두번째로 cgroups는 하드웨어 리소스에 대해 제어를 가능하게 해준다. 메모리, CPU , I/O 등을 제어해 프로세스에 할당해 줄 수 있다.

 

두개의 리눅스 기술을 이용하여 컨테이너를 구현할 수 있고 컨테이너를 통해 프로세스가 실행되는 환경 종속성을 없애줄 수 있다.

'공부 > OTHERS' 카테고리의 다른 글

[Docker] 도커의 네트워크 네임스페이스  (0) 2021.05.26
[Linux] 네트워크 네임스페이스, veth  (0) 2021.05.25

[Docker] 도커의 네트워크 네임스페이스 공부/OTHERS

Date 2021. 5. 26. 21:25

1. 도커의 네트워크 디바이스

도커의 네트워크는 기본적으로 docker0라는 가상 Bridge를 중심으로 구성된다.
이외에도 호스트 네트워크를 사용하는 host, 그리고 null 즉 네트워크 없이 구성할 수도 있다.

 

2. 컨테이너 생성 시 네트워크

먼저 생성된 컨테이너는 veth 쌍을 할당받는다. 하나는 eth0 (컨테이너용), 또하나는 vethXXX로 이름이 붙여지고 docker0 브릿지에 붙는 peer이다.

이렇게 구성함으로써 컨테이너(eth0) - 호스트(vethXXX) - 브릿지(docker0) 형태로 구성되어 패킷이 오갈 수 있는 통로를 만들어준다.

컨테이너 두개를 생성하여 veth pair가 두개 생성되어 호스트에 붙은 상태다.

 


보다시피 master가 docker0으로 되어있다.

또한 여기서 컨테이너 내부에서는 route 경로로 172.0.0.1(docker0) 가 설정된 것을 볼 수 있는데 이는 컨테이너에서 나가는 패킷들은 모두 docker0으로 향하게 한다.

마지막으로 호스트에서는, docker0 브릿지로 FORWARD 되는 패킷들을 모두 ACCEPT 하여 컨테이너와 외부 간 통신이 가능하게 해준다.

 

이를 통해 컨테이너간, 또 컨테이너와 외부 간 네트워크 통신을 가능하게 해준다.

'공부 > OTHERS' 카테고리의 다른 글

[Container] Container와 VM  (0) 2021.05.27
[Linux] 네트워크 네임스페이스, veth  (0) 2021.05.25

Recent Posts

Popular posts

Recent Comments

Tag List

클라우드 k8s 도커 테라폼 인증 IAC AWS 인가 API 알고리즘 컨테이너 리눅스 JWT ORM 백준 운영체제 DNS TypeScript GCP 파이썬 DB 네트워크 JavaScript 네임스페이스
Total : Today : Yesterday :
Blog powered by Tistory, Designed by hanarotg