Hamutaro

안녕하세요,,,

오늘도 모닝30? 없습니다

내일부터? 자리 바꿉니다.

그럼 레츠고.


오늘의 수업

교시 무엇
2교시 지속 검증 · 세션 만료
3교시 정책 로그 · 판단과 집행 맞춰 보기
4교시 점수 규칙 조정 · 점검 결과 정리하기
5교시 어제 명령 복습 · 서버 두 대 켜고 접속 기록 구분해 읽기
6교시 내 이미지 만들기 (Dockerfile)
7교시 이미지 버전 다루기 · 되돌리기 · 정리 · 올리기

2교시 지속 검증 · 세션 만료

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「정산 포털에 로그인한 직원이 자리를 비워도 접속이 계속 유지됩니다. 로그인할 때만 확인하지 말고 접속하는 동안에도 확인하고, 시간이 지나면 허용을 취소할 수 있나요?」

이번에는 자원마다 접속 유지 시간을 다르게 두고 세션 상태를 판정하는 함수를 만들었다.

접속 중에 상태가 바뀌었을 때 유지 · 재인증 · 종료 중 어떤 조치를 해야 하는지도 확인했다.

왜 필요한가

어제 만든 판단 함수는 요청이 들어오는 순간만 판단했다.

로그인한 뒤 기기 상태가 바뀌거나 직원이 퇴사 처리돼도 기존 접속이 그대로 유지된다면 문제가 될 수 있다.

접속이 오래 유지되면 사용자가 자리를 비운 사이 다른 사람이 사용할 수도 있고, 탈취된 세션이 계속 사용될 수도 있다.

그래서 위험한 자원일수록 접속 유지 시간을 짧게 두는 방법을 사용했다.

최소권한을 접근 범위뿐 아니라 시간에도 적용한 것이다.

2.1 세션과 지속 검증

세션

로그인한 뒤 서버가 해당 접속의 상태를 저장해 두는 것이다.

누가 언제부터 접속했는지 등을 서버가 기억한다.

서버가 발급한 토큰을 요청할 때마다 보여 주면 로그인된 접속으로 판단할 수 있다.

지속 검증

Continuous Verification

로그인할 때 한 번만 확인하는 것이 아니라 접속 중에도 계속 상태를 다시 확인하는 방식이다.

세션 만료

정해진 유지 시간이 지나면 기존 허용이 끝나고 다시 로그인해야 하는 것이다.

재인증

사용자가 실제 본인인지 다시 확인하는 것이다.

예를 들어 비밀번호나 MFA를 다시 요구할 수 있다.

회수

이미 허용된 접속을 중간에 취소하고 세션을 끝내는 것이다.

접속 중에 상황이 바뀌면 다음 세 가지 중 하나를 선택했다.

조치 언제 예
유지 허용했던 근거가 그대로인 경우 평소와 같은 기기 · 위치 · 업무
재인증 근거가 불확실해졌지만 본인 확인으로 해결할 수 있는 경우 만료 시각이 가까워짐
종료(회수) 허용 근거가 사라졌고 재인증으로도 해결할 수 없는 경우 계정이 비활성화됨

실제 서비스에서도 비슷한 기능을 사용한다.

Microsoft Entra 조건부 액세스에는 다시 로그인하기 전까지 접근을 유지할 시간을 정하는 로그인 빈도 기능이 있다.

Cloudflare Access에서도 앱마다 세션 지속 시간을 설정할 수 있다.

2.2 자원마다 다른 유지 시간

이번에는 자원마다 세션 유지 시간을 다르게 설정했다.

자원 유지 시간 이유
정산 내역 조회 30분 읽기 중심이라 위험이 중간
계정 권한 변경 5분 계정을 직접 변경할 수 있어 위험이 큼

세션 상태는 접속한 뒤 지난 시간과 유지 시간을 비교해서 판단했다.

상태 조건
종료 경과 시간이 유지 시간보다 큼
재인증 경과 시간이 유지 시간의 0.8배 이상
유지 위 두 조건에 해당하지 않음

정산 조회의 유지 시간이 30분이라면 0.8배는 24분이다.

경과 시간 비교 상태
10분 24보다 작음 유지
24분 24 이상, 30 이하 재인증
30분 30보다 크지 않음 재인증
31분 30보다 큼 종료

조건을 확인할 때는 종료를 먼저 확인하고 그다음 재인증을 확인했다.

31분은 재인증 조건에도 해당할 수 있지만 종료 조건을 먼저 확인했기 때문에 종료가 적용됐다.

함수는 return을 만나면 그 자리에서 끝나는 방식이었다.

2.3 파일 만들기

이번부터 파일을 만드는 방법은 세 가지 중 하나를 선택했다.

방법 1 · VS Code

VS Code에서 network_zt 폴더를 선택한 뒤 새 파일을 만들었다.

day07_2-1_session_state.py

파일을 열고 코드를 붙여 넣은 뒤 저장했다.

방법 2 · touch

먼저 현재 위치를 확인했다.

pwd

network_zt 폴더가 아니라면 이동했다.

cd network_zt

빈 파일을 만들었다.

touch day07_2-1_session_state.py

그다음 VS Code에서 파일을 열어 내용을 작성했다.

방법 3 · vim

vim day07_2-1_session_state.py

순서는 다음과 같았다.

vim 파일이름
→ i
→ 내용 입력 또는 붙여넣기
→ Esc
→ :wq
→ Enter

붙여넣은 코드의 들여쓰기가 계속 밀리면 :q!로 저장하지 않고 나와 VS Code나 touch 방식을 사용했다.

2교시 한눈에

하려는 일 방법
세션 상태 판정 경과 분 > 유지 시간 → 종료 / 경과 분 ≥ 유지 시간 × 0.8 → 재인증 / 그 외 → 유지
자원별 유지 시간 SESSION_LIMITS[session["resource"]]
접속 중 변화에 대한 조치 근거가 그대로면 유지, 본인 확인으로 해결되면 재인증, 해결되지 않으면 종료

3교시 정책 로그 · 판단과 집행 맞춰 보기

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「제보가 들어왔습니다. 정책 로그에는 거부라고 적혀 있는 요청이 앱 기록에는 성공으로 남아 있다고 합니다. 결정이 제대로 집행됐는지 확인해 주세요.」

이번에는 정책 로그와 앱 접근 기록을 요청 번호로 맞춰 보고, 서로 일치하지 않는 요청을 찾아 유형별로 구분했다.

왜 필요한가

PDP가 요청을 거부했다고 결정해도 PEP가 그 결정을 제대로 집행하지 않으면 실제 요청은 통과할 수 있다.

정책 로그만 보면 거부된 것처럼 보여도 실제 앱에서는 정상 처리됐을 수 있다.

그래서 정책 로그와 앱 접근 기록을 같은 요청 번호로 맞춰 확인해야 했다.

요청이 많아지면 사람이 하나씩 비교하기 어려우므로 문제가 발생한 유형별로 개수도 세었다.

3.1 정책 로그와 앱 접근 기록

PDP

Policy Decision Point

요청을 확인하고 점수를 계산해 허용 · 추가확인 · 거부 중 하나를 결정했다.

결정만 할 뿐 실제 요청을 막거나 통과시키지는 않았다.

PEP

Policy Enforcement Point

PDP가 내린 결정대로 요청을 실제로 허용하거나 차단했다.

앱에 요청이 전달되기 전에 위치했다.

요청 번호

RID, Request ID

요청마다 하나씩 붙는 번호이다.

정책 로그와 앱 접근 기록의 같은 요청에는 같은 RID가 들어 있었다.

따라서 RID를 기준으로 두 기록을 비교할 수 있었다.

정책 로그

PDP가 요청마다 남긴 결정 기록이다.

주요 항목은 다음과 같았다.

rid
time
user
decision
score
reasons

앱 접근 기록

앱이 요청을 실제로 처리한 결과이다.

주요 항목은 다음과 같았다.

rid
time
user
status

응답 번호는 다음처럼 사용했다.

응답 번호 뜻
200 처리됨
401 추가 확인 필요
403 차단됨

PDP의 결정과 앱의 응답 번호는 다음처럼 맞아야 했다.

PDP 결정 앱에서 나와야 하는 응답
허용 200
추가확인 401
거부 403

두 기록을 비교하면 결과를 네 가지로 나눌 수 있었다.

유형 모양 뜻 위험
일치 결정과 응답이 같음 결정대로 집행됨 없음
집행 누락 앱이 결정보다 약한 응답 결정이 제대로 적용되지 않음 높음
과집행 앱이 결정보다 강한 응답 정상 요청까지 막음 업무 불편
우회 앱 기록에만 있고 정책 로그에는 없음 PDP를 거치지 않은 경로 높음

예를 들어 요청 번호 101은 다음과 같았다.

기록 값
정책 로그 101 거부 → 원래 403이어야 함
앱 접근 기록 101 200
판정 200 ≠ 403 → 집행 누락

PDP에서는 거부했지만 실제 앱에서는 요청이 정상 처리됐기 때문에 집행 누락으로 판단했다.

코드에서는 딕셔너리를 이용해 요청 번호별 값을 저장했다.

d[키] = 값

값을 꺼낼 때는 .get()을 사용할 수 있었다.

d.get(키)

키가 없으면 None이 나왔다.

유형별 개수는 다음과 같은 방식으로 셌다.

counts[kind] = counts.get(kind, 0) + 1

3교시 한눈에

하려는 일 방법
두 기록을 요청 번호로 맞추기 access_status[a["rid"]] = a["status"]
요청 번호로 값 꺼내기 access_status.get(p["rid"])
결정과 응답 대조 EXPECTED[p["decision"]]와 앱의 status 비교
어긋난 유형 집행 누락 · 과집행 · 우회
약한지 강한지 비교 STRENGTH[status]와 STRENGTH[expected] 비교
유형별 개수 세기 counts[kind] = counts.get(kind, 0) + 1

4교시 점수 규칙 조정 · 점검 결과 정리하기

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「재무팀 junho 가 정산 마감 주간이라 추가 확인이 계속 떠서 일을 못 한다고 합니다. 점수 규칙을 어떻게 조정하면 좋은지 숫자로 알려 주시고, 3교시에 찾은 문제와 함께 임원 보고용 한 장으로 정리해 주세요.」

이번에는 점수 규칙을 세 가지 방식으로 바꿔 보고 오탐과 미탐이 얼마나 발생하는지 비교했다.

그 결과와 3교시에서 찾은 문제를 같이 정리해 문서로 만들었다.

왜 필요한가

정상 직원에게 추가 인증이나 차단이 계속 발생하면 업무에 불편이 생긴다.

이런 상황이 반복되면 결국 보안 규칙 자체를 무시하거나 꺼 버릴 수도 있다.

하지만 정상 요청을 덜 막으려고 기준을 너무 완화하면 위험한 요청을 놓칠 수 있다.

그래서 규칙을 바꿀 때는 오탐과 미탐을 같이 확인해야 했다.

4.1 오탐 · 미탐과 점수 규칙 조정

오탐

False Positive

실제로는 정상 요청인데 규칙이 추가확인이나 거부로 판정한 경우이다.

정상 사용자의 업무가 막히거나 느려질 수 있다.

예를 들어 정산 마감 기간에 재무팀 직원이 평소보다 많은 데이터를 조회했는데 이를 이상 행동으로 판단하면 오탐이 된다.

미탐

False Negative

실제로는 위험한 요청인데 허용하거나 너무 약하게 판정한 경우이다.

위험한 요청이 차단되지 않을 수 있다.

예를 들어 대량 조회 기준을 너무 높이면 위험한 요청이 대량 조회 점수를 받지 못할 수 있다.

규칙 판정 실제 정상 실제 위험
허용 맞음 미탐
추가확인 · 거부 오탐 거부면 맞음, 추가확인이면 미탐

이번 실습에서는 위험한 요청의 올바른 결정은 거부로 정했다.

junho의 요청은 모두 등록 기기를 사용하고 MFA도 통과했기 때문에 두 가지 점수만 확인했다.

조건 점수
해외 접속 +30
20건 이상 조회 +30

결정 기준은 다음과 같았다.

50점 이상 → 거부
20점 이상 → 추가확인
그 아래 → 허용

규칙을 세 가지 방식으로 바꿔 봤다.

안 바꾸는 것
A 대량 조회 기준을 20건에서 50건으로 올림
B 대량 조회 점수를 +30에서 +10으로 낮춤
C 정산 마감 주간에는 재무팀 계정의 대량 조회 점수를 0으로 함

각 안을 같은 요청에 적용한 뒤 오탐과 미탐의 개수를 비교했다.

코드에서는 튜플을 세 변수로 나눠 받는 방법도 사용했다.

for name, threshold, points in PLANS:

두 조건을 같이 확인할 때는 and를 사용했다.

조건1 and 조건2

보고서 정리

점검 결과는 다음 순서로 작성했다.

결론
→ 근거
→ 권고

결론에는 확인된 사실을 적었다.

근거에는 요청 번호와 실제 숫자를 적었다.

권고에는 어떤 규칙을 조정할지와 추가로 확인할 자료를 적었다.

전문용어를 그대로 나열하는 것보다 처음 등장할 때 쉬운 말로 같이 설명하는 방식이 좋았다.

새 문서는 다음 세 가지 방법 중 하나로 만들 수 있었다.

VS Code 새 파일
touch day07_log_summary.md
vim day07_log_summary.md

저장된 내용은 다음 명령으로 확인했다.

cat day07_log_summary.md

4교시 한눈에

하려는 일 방법
점수 규칙 조정 비교 같은 요청에 각각 적용해서 오탐 · 미탐 개수 비교
조정안 꺼내기 for name, threshold, points in PLANS:
보고서 구조 결론 → 근거 → 권고
전문용어 처음 나올 때 쉬운 말로 같이 설명
문서 만들기 VS Code · touch · vim 중 하나
저장 내용 확인 cat day07_log_summary.md

5교시 어제 명령 복습 · 서버 두 대 켜고 접속 기록 구분해 읽기

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「고객용 안내 페이지와 직원용 안내 페이지를 서버 두 대로 따로 켜 주세요. 고객용(site-three)은 8082번, 직원용(site-four)은 8083번입니다. 이상한 접속이 생기면 어느 페이지에 온 요청인지 바로 가려야 하니, 접속 기록이 서버마다 따로 남는지 확인해 주세요.」

어제 사용했던 Docker 명령으로 nginx 서버 두 대를 실행하고, 각각의 서버에 로그가 따로 남는지 확인했다.

왜 필요한가

Docker 명령은 처음에는 옵션이 많아서 헷갈렸다.

같은 명령을 한 번 더 사용하면서 서버 실행 · 확인 · 로그 조회 · 종료 · 삭제 순서를 다시 익혔다.

같은 이미지로 여러 서버를 실행할 때는 컨테이너 이름과 PC 포트 번호를 다르게 설정했다.

서버가 여러 대라면 로그도 서버별로 구분해서 확인해야 했다.

5.1 어제 명령 한눈에

명령 필요한 상황 결과
docker run -d --name 이름 -p 내포트:80 이미지 서버 실행 컨테이너가 백그라운드로 실행됨
-v "$(pwd)/폴더:/usr/share/nginx/html:ro" 내 PC 파일 연결 내 폴더의 페이지를 서버가 보여 줌
docker ps 실행 중인 서버 확인 실행 중인 컨테이너만 표시
docker ps -a 종료된 서버까지 확인 Exited 상태까지 표시
docker logs 이름 한 서버의 로그 확인 해당 컨테이너의 기록만 표시
docker exec 이름 명령 서버 안에서 명령 하나 실행 명령 실행 후 바로 돌아옴
docker stop 이름 서버 종료 컨테이너가 Exited 상태가 됨
docker rm 이름 컨테이너 삭제 목록에서도 사라짐

5.2 서버가 두 대일 때 구분

같은 nginx 이미지를 사용해 서버 두 대를 만들었다.

nginx:1.28
   |
   ├─ web-three
   |    ├─ 내 PC 포트: 8082
   |    └─ 폴더: site-three
   |
   └─ web-four
        ├─ 내 PC 포트: 8083
        └─ 폴더: site-four

두 서버가 공통으로 사용하는 것은 이미지였다.

nginx:1.28

서버마다 달랐던 것은 다음 세 가지였다.

  • 컨테이너 이름
  • 내 PC 포트
  • 연결한 폴더

그래서 같은 이미지로 실행했어도 고객용과 직원용 화면을 서로 다르게 만들 수 있었다.

로그도 컨테이너별로 따로 남았다.

docker logs web-three

에는 8082번으로 접속한 요청이 남고,

docker logs web-four

에는 8083번으로 접속한 요청이 남았다.

여러 컨테이너 이름을 한 명령에 같이 적을 수도 있었다.

docker stop web-three web-four

5교시 한눈에

하려는 일 명령 · 옵션
서버 켜기 docker run -d --name 이름 -p 내포트:80 -v "$(pwd)/폴더:/usr/share/nginx/html:ro" nginx:1.28
서버 여러 대 구분 이름 · 내 PC 포트 · 연결 폴더
한 서버의 로그 확인 docker logs 이름
서버 안에서 명령 하나 실행 docker exec 이름 명령
여러 서버 한 번에 종료 docker stop 이름1 이름2
여러 서버 삭제 docker rm 이름1 이름2

6교시 내 이미지 만들기 (Dockerfile)

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「안내 페이지 서버를 다른 PC에도 똑같이 넘기고 싶습니다. 5교시처럼 -v 로 폴더를 연결하면 폴더도 같이 보내야 하는데, 폴더 없이 이미지 하나만 보내도 서버가 똑같이 켜지게 할 수는 없나요?」

이번에는 웹 페이지 파일을 Docker 이미지 안에 직접 넣어서 내 이미지를 만들었다.

파일을 수정한 뒤에는 이미지를 다시 만들어야 변경 내용이 적용된다는 것도 확인했다.

왜 필요한가

-v 방식은 nginx 이미지뿐 아니라 연결할 폴더도 같이 있어야 했다.

다른 PC에서 똑같은 서버를 실행하려면 이미지와 폴더를 모두 전달해야 했다.

반대로 웹 페이지 파일을 이미지 안에 넣어 두면 이미지 하나만 있으면 같은 화면을 실행할 수 있었다.

이미지를 만드는 방법을 적는 파일이 Dockerfile이었다.

6.1 Dockerfile → build → image → run → container

전체 흐름은 다음과 같았다.

Dockerfile
   |
   ├─ FROM nginx:1.28
   └─ COPY site-three/index.html /usr/share/nginx/html/index.html
   |
   | docker build
   v
이미지 my-nginx:1
   |
   | docker run
   v
컨테이너

Dockerfile은 이미지를 만드는 방법을 적어 둔 텍스트 파일이다.

파일 이름은 정확히

Dockerfile

로 사용했다.

대문자 D로 시작하고 확장자는 없었다.

6.2 Dockerfile 두 줄의 뜻

명령 형식 하는 일
FROM FROM 이미지:태그 기존 이미지를 기반으로 새 이미지를 만듦
COPY COPY 내PC경로 이미지안경로 내 파일을 이미지 안에 복사

예를 들면 다음과 같았다.

FROM nginx:1.28
COPY site-three/index.html /usr/share/nginx/html/index.html

FROM nginx:1.28은 nginx 프로그램과 기본 파일을 새 이미지의 기반으로 사용했다.

COPY는 내 PC의 index.html을 nginx가 사용하는 위치로 복사했다.

nginx가 기본으로 보여 주는 페이지는 다음 위치에 있었다.

/usr/share/nginx/html/index.html

같은 위치에 내 파일을 복사하면 기본 nginx 화면 대신 내가 만든 페이지가 보였다.

COPY 앞쪽의 경로는 Dockerfile이 있는 폴더를 기준으로 했다.

6.3 이미지 만들기

Dockerfile을 만든 뒤 이미지로 빌드했다.

docker build -t my-nginx:1 .

각 부분의 뜻은 다음과 같았다.

부분 뜻
docker build Dockerfile을 읽어 이미지 생성
-t my-nginx:1 이미지에 이름과 태그 지정
. 현재 폴더의 Dockerfile 사용

마지막의 .도 필요한 값이었다.

점을 빼면 Dockerfile을 찾을 위치가 지정되지 않아 오류가 발생했다.

만든 이미지는 다음 명령으로 확인했다.

docker images

새 이미지로 서버도 실행할 수 있었다.

docker run -d --name 이름 -p 포트:80 my-nginx:1

6.4 -v 방식과 이미지에 넣는 방식

두 방법에는 차이가 있었다.

-v 방식

내 PC
site-three/index.html
        |
        | 연결
        v
컨테이너

내 PC의 파일을 컨테이너에서 계속 읽고 있기 때문에 파일을 수정하면 바로 반영됐다.

이미지에 COPY

내 PC 파일
    |
    | docker build 시 COPY
    v
이미지
    |
    v
컨테이너

파일은 이미지를 만드는 순간 복사됐다.

이미지를 만든 뒤 내 PC의 파일을 수정해도 기존 이미지는 바뀌지 않았다.

구분 -v 연결 이미지에 COPY
서버를 넘길 때 이미지 + 폴더 필요 이미지 하나만 필요
파일 수정 새로 고침하면 반영 다시 build 해야 반영
잘 맞는 경우 자주 바뀌는 설정 · 페이지 내용이 자주 바뀌지 않는 서버

6교시 한눈에

하려는 일 명령 · 파일
이미지를 만드는 파일 Dockerfile
기존 이미지 지정 FROM
내 파일 넣기 COPY
이미지 만들기 docker build -t 이름:태그 .
이미지 확인 docker images
내 이미지로 서버 실행 docker run -d --name 이름 -p 포트:80 이름:태그
파일 수정 후 반영 새 태그로 다시 build

7교시 이미지 버전 다루기 · 되돌리기 · 정리 · 올리기

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「안내 문구를 바꿨는데 서버에 반영이 안 됩니다. 반영해 주세요. 그리고 새 버전에 문제가 있으면 이전 버전으로 바로 돌아갈 수 있어야 하고, 쓰지 않는 이미지는 정리해 주세요.」

파일을 수정한 뒤 새 이미지로 반영하고, 문제가 생긴 상황을 가정해 이전 버전으로 되돌리는 방법을 확인했다.

사용하지 않는 이미지도 정리하고 마지막에는 GitHub에 올렸다.

왜 필요한가

Docker 이미지는 이미지를 만들 당시의 파일을 그대로 가지고 있다.

따라서 원본 파일을 수정한다고 이미 만들어진 이미지가 자동으로 바뀌지는 않았다.

수정 내용을 반영하려면 다시 빌드해야 했다.

이미지에 :1, :2처럼 버전을 나타내는 태그를 붙여 두면 새로운 버전에서 문제가 생겼을 때 이전 이미지로 다시 실행할 수 있었다.

사용하지 않는 이미지는 계속 디스크 공간을 사용하기 때문에 필요 없는 이미지는 삭제했다.

새 버전 만들기

파일을 수정한 뒤 새로운 태그를 붙여 이미지를 다시 만들었다.

예:

docker build -t my-nginx:2 .

기존 서버를 삭제하고 새 이미지로 다시 실행했다.

docker rm -f 이름
docker run -d --name 이름 -p 포트:80 my-nginx:2

이렇게 해야 수정한 파일이 실제 서버에 반영됐다.

이전 버전으로 되돌리기

새 이미지에 문제가 생겼다면 현재 컨테이너를 지우고 이전 태그의 이미지로 다시 실행했다.

docker rm -f 이름
docker run -d --name 이름 -p 포트:80 my-nginx:1

이미지 버전을 따로 남겨 두면 이전 상태로 빠르게 되돌릴 수 있었다.

이미지 정리하기

현재 이미지는 다음 명령으로 확인했다.

docker images

사용하지 않는 이미지는 다음 명령으로 삭제했다.

docker rmi 이름:태그

컨테이너와 이미지를 삭제하는 명령은 서로 달랐다.

docker rm  → 컨테이너 삭제
docker rmi → 이미지 삭제

rmi의 i를 image의 i로 기억하면 구분하기 쉬웠다.

현재 컨테이너가 사용하는 이미지는 바로 삭제할 수 없었다.

이 경우 먼저 컨테이너를 삭제해야 했다.

docker rm -f 이름

그다음 이미지를 지웠다.

docker rmi 이름:태그

GitHub에 올리기

마지막으로 오늘 만든 파일을 확인했다.

git status

변경한 파일을 추가했다.

git add .

커밋했다.

git commit -m "..."

원격 저장소에 올렸다.

git push

7교시 한눈에

하려는 일 명령 · 방법
파일 수정 후 반영 새 태그로 다시 build → 컨테이너 교체
이전 버전으로 되돌리기 현재 컨테이너 삭제 → 이전 태그 이미지로 실행
이미지 목록 확인 docker images
컨테이너 삭제 docker rm
이미지 삭제 docker rmi 이름:태그
사용 중인 이미지 삭제가 안 될 때 컨테이너부터 삭제
GitHub에 올리기 git status → git add . → git commit → git push

 

 

 

오늘은 좀 덥네요,,, 강의실이 창문도 없고 오직 벽뿐인데 컴퓨터가 많아서 더운가봐요,,,

겨울에는 따뜻하겠다.. 겨울을 기대해 봐야겠어요..

그럼 아됴

오늘 오전 30분은 없었습ㄴㅣ다....

잠깐의 자습시간을 조금 가지구..? 버추얼을 했구용

바로 들어가기~~

 


오늘의 순서

교시 무엇
2교시 경계 기반 보안의 한계 · Zero Trust · 5대 원칙
3교시 점수로 판단하는 함수 (PDP)
4교시 PDP 와 PEP · ZT 성숙도 점수 · A사 적용 방안 문서
5교시 왜 도커인가 · 이미지와 컨테이너 · 같이 설치하기
6교시 nginx 서버 켜고 접속 기록 읽기
7교시 내 페이지 연결 · 두 서버 · 올리기

 


 

2교시 경계 기반 보안의 한계 · Zero Trust · 5대 원칙

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「월요일 아침 정산 포털 기록을 보니 새벽에 정산 내역이 대량으로 조회됐습니다. 방화벽은 아무것도 막지 않았습니다. 무슨 일이고 왜 통과됐나요?」

이 교시에서는 접근 기록에서 의심스러운 줄을 찾고, 5대 원칙의 어느 칸이 비어 있었는지 확인했다.

또 기록만으로 말할 수 있는 것과 없는 것을 구분했다.

왜 필요한가

지난주에 본 방화벽 · VPN 은 접속이 시작되는 곳에서 확인하는 방식이었다.

한 번 통과한 뒤에 그 계정이 무엇을 하는지는 따로 확인하지 않았다.

로그인이 성공한 요청 안에도 정상과 이상이 섞여 있기 때문에 어떤 항목을 확인해야 하는지 알아야 규칙으로 만들 수 있었다.

또 기록에 적힌 값과 그 값으로 추정한 내용을 구분해야 과장 없이 보고할 수 있었다.

2.1 경계 기반 보안과 Zero Trust

경계 기반 보안

회사 네트워크 안은 신뢰하고 밖은 의심하는 방식이다.

방화벽 · VPN 이라는 경계를 통과하면 내부 자원에 넓게 접근할 수 있다.

Zero Trust

누구도 기본적으로 신뢰하지 않고, 접근할 때마다 확인한다는 보안 원칙이다.

미국 NIST의 SP 800-207 문서에서 이 구조를 정리했다.

자원

보호할 대상을 뜻한다.

같은 포털 안에서도 정산 내역 조회와 계정 권한 변경은 서로 다른 자원이다.

횡이동

침입한 뒤 내부에서 다른 서버로 옮겨 가면서 공격 범위를 넓히는 것을 말한다.

경계 기반 보안에서는 내부 이동을 막기 어렵다.

기준 경계 기반 보안 Zero Trust
신뢰 전제 경계 안으로 들어오면 신뢰한다 안팎 구분 없이 기본적으로 신뢰하지 않는다
검증 시점 로그인할 때 한 번 접근할 때마다, 세션 중에도 반복
접근 범위 인증되면 내부에 넓게 접근 업무에 필요한 자원에만 최소한으로 접근

Zero Trust 가 모든 이상 행동을 막는 것은 아니다.

정상 계정 · 정상 기기 · 평소 시간에 자기 업무 시스템에서 자료 수만 건을 내려받는 경우처럼 접근 자체는 정상인데 행동이 이상할 수도 있다.

이런 경우는 접근을 허용할지 정하는 것만으로는 찾기 어렵고, 사용 기록을 계속 분석하는 이상탐지가 따로 필요하다.

실제 서비스로는 Cloudflare Access가 사내 앱마다 접근 정책을 걸고 사용자 신원과 기기 상태를 확인한다.

Microsoft Entra 조건부 액세스는 회사 기기가 보안 기준을 지킨 기기일 때만 접속하도록 정책을 만들 수 있다.

2.2 5대 원칙 — 요청 하나를 다섯 칸으로 읽기

Zero Trust 는 제품 하나가 아니라 확인할 항목의 묶음이다.

요청 하나를 다섯 칸으로 나누면 어느 부분이 부족했는지 확인할 수 있다.

ID

이 사용자가 진짜 본인인지 확인하는 항목이다.

MFA는 비밀번호 외에 휴대폰 승인 같은 인증 수단을 하나 더 확인하는 방식이다.

Device

접속하는 기기가 회사 보안 기준을 지키는지 확인한다.

등록된 기기인지, 백신 · 패치 상태가 괜찮은지 등을 확인한다.

Network

요청이 필요한 자원에만 접근하는지 확인한다.

마이크로 세그멘테이션은 네트워크를 작은 구역으로 나누고 구역 사이의 통신을 제한하는 방식이다.

Application

사용자가 해당 앱의 기능을 사용할 권한이 있는지 확인한다.

Policy

시간 · 위치 · 위험도에 따라 정책을 다르게 적용한다.

예를 들어 새벽 로그인이나 해외 IP 접속이라면 추가 인증을 요구할 수 있다.

칸 묻는 것 확인하는 예 대표 제품
ID 이 사용자가 진짜 본인인가 비밀번호 + MFA Microsoft Entra ID
Device 기기가 회사 기준을 지키나 등록 기기 · 백신 · 패치 · 디스크 암호화 Microsoft Intune
Network 필요한 자원에만 닿나 구역을 나누고 구역 사이 통신 제한 방화벽 구역 규칙
Application 이 앱의 권한이 있나 앱마다 따로 접근 정책 Cloudflare Access
Policy 상황에 따라 정책이 바뀌나 해외 IP · 새벽 로그인이면 추가 인증 Microsoft Entra 조건부 액세스

문서마다 항목 이름이나 개수가 조금씩 다를 수 있지만 이번 과정에서는 위 다섯 가지로 구분했다.

요청 하나가 한 항목을 통과해도 다른 항목에서 막힐 수 있다.

어느 항목에서 문제가 생겼는지 확인하면 어디를 고쳐야 하는지도 알 수 있다.

A사 재무팀 junho의 정상적인 정산 조회를 다섯 항목으로 보면 다음과 같았다.

칸 이 요청에서 확인한 것 결과
ID 계정 junho, 로그인 방식 비밀번호 + MFA 정상
Device 기기 NB-0522 는 junho 의 등록 기기이고 보안 상태 정상 정상
Network 사내 대역 10.20.3.14 에서 정산 포털로 접속 정상
Application junho 는 정산 내역(SETTLE) 담당 정상
Policy 낮 14시, 평소 조회량 12건 정상

2.3 기록으로 단정할 수 있는 것과 없는 것

확인된 사실은 기록에 실제로 적힌 값이다.

시각 · 계정 · 기기 · 출발 IP · 건수 · 결과 등이 여기에 해당했다.

추정은 기록을 보고 짐작한 내용이다.

예를 들어 「본인이 아닐 것이다」는 기록에 직접 적힌 값이 아니므로 추정이다.

출발 IP가 사내 대역이라는 것은 사내망에서 접속했다는 사실일 뿐, 그 기기가 회사 등록 기기라는 뜻은 아니다.

기기 등록 여부는 별도의 기록을 확인해야 한다.

「로그인 성공」이라는 기록에도 계정 확인, 비밀번호 확인, MFA 여부가 섞여 있기 때문에 무엇을 확인하고 성공한 것인지 따로 봐야 했다.

기록만으로 알 수 없는 것은 모른다고 쓰고, 어떤 자료를 추가로 확인해야 하는지 같이 적는 것이 중요했다.

2교시 한눈에

하려는 일 보는 곳
의심 줄 찾기 시각 · 기기 · 자원 · 건수 · 로그인 방식을 등록 정보와 같은 계정의 다른 줄에 대조
이상해 보이지만 정상인 줄 거르기 등록 정보의 설명
한 줄씩은 정상인데 모으면 이상한 줄 맡은 자원과 대조하고 같은 계정의 반복 횟수와 건수를 합산
요청이 어느 칸에서 걸리는지 ID → Device → Network → Application → Policy 순서
정상 로그인인데 걸린다면 Policy 칸
단정할 수 있는지 기록에 적힌 값만 사실, 나머지는 추정

 

3교시 점수로 판단하는 함수 (PDP)

오늘 들어온 일

A사 보안 담당이 보낸 메시지:

「2교시에 본 새벽 사건 같은 요청을 앞으로는 자동으로 거르고 싶습니다. 요청이 들어올 때마다 허용 · 추가 확인 · 거부를 정하는 규칙을 코드로 만들어 주세요.」

이번에는 점수로 판단하는 파이썬 함수를 읽고, 요청을 한꺼번에 판정했다.

왜 필요한가

로그인이 성공한 요청을 사람이 하나씩 읽기는 어렵다.

규칙을 코드로 만들면 모든 요청을 같은 기준으로 바로 판정할 수 있다.

이 규칙을 결정하는 부분이 PDP이다.

3.0 파일 만들기

이번부터 파일은 터미널에서 vim으로 만들었다.

먼저 위치를 확인했다.

pwd

결과가 network_zt 폴더가 아니라면 이동했다.

cd network_zt

vim으로 파일을 만드는 순서는 다음과 같았다.

순서 입력 하는 일
① vim 파일이름 파일을 연다
② i 입력 모드로 들어간다
③ 붙여넣기 코드를 붙여 넣는다
④ Esc → :wq → Enter 저장하고 나간다

키가 제대로 동작하지 않으면 한/영 상태를 확인하고 Esc를 먼저 누른 뒤 명령을 입력했다.

붙여넣기 과정에서 공백이 계속 밀리면 :q!로 저장하지 않고 나와 touch로 파일을 만든 뒤 VS Code에서 수정할 수도 있었다.

3.1 PDP 와 점수 판단

PDP

Policy Decision Point

요청을 받아 허용 · 추가 확인 · 거부를 결정하는 곳이다.

이번에는 파이썬 함수 하나가 이 역할을 했다.

필수 조건

하나라도 어긋나면 점수와 관계없이 바로 거부하는 조건이다.

예:

  • 재직 중인 계정인지
  • 등록된 기기인지

위험 점수

이상한 신호마다 점수를 더해 합계로 판단하는 방식이다.

0점에서 시작했다.

추가 확인

비밀번호만으로 부족할 때 인증을 한 번 더 요구하는 단계이다.

허용과 거부 사이의 단계라고 볼 수 있다.

최소권한

업무에 필요한 만큼만 권한을 주는 원칙이다.

더 중요한 자원일수록 기준도 더 엄격하게 정할 수 있다.

구분 정산 내역 조회 계정 권한 변경
필수 조건 재직 중 · 등록 기기 재직 중 · 등록 기기 · 역할이 account_admin
기기 보안 상태 이상 +40 3-1에서 정함
MFA 안 함 +20 3-1에서 정함
해외에서 접속 +30 3-1에서 정함
새벽 접속 +20 보지 않음
20건 이상 조회 +30 보지 않음
결정 50점 이상 거부 · 20점 이상 추가확인 · 그 아래 허용 50점 이상 거부 · 10점 이상 추가확인 · 그 아래 허용

ACCOUNTS.get(req["user"])를 사용하면 계정 정보를 찾고 없을 경우 None을 받을 수 있었다.

reasons.append()로 판단 이유를 리스트에 추가했다.

return "거부", reasons처럼 값 두 개를 한 번에 리턴할 수도 있었다.

함수는 return을 만나면 바로 끝나기 때문에 필수 조건에서 거부되면 아래의 점수 계산은 실행되지 않았다.

3.2 판단 함수

ACCOUNTS = {
    "seoyeon": {"employed": True,  "device": "NB-0417", "role": "sales"},
    "junho":   {"employed": True,  "device": "NB-0522", "role": "finance"},
    "gaeun":   {"employed": True,  "device": "NB-0188", "role": "account_admin"},
    "dami":    {"employed": False, "device": "NB-0333", "role": "sales"},
}

정산 내역 조회 요청을 판단하는 함수는 다음 구조였다.

def decide_settlement(req):
    """정산 내역 조회 요청을 판단해 (결정, 이유 목록)을 리턴한다"""

    account = ACCOUNTS.get(req["user"])

    if account is None or not account["employed"]:
        return "거부", ["재직 중인 계정이 아님"]

    if req["device"] != account["device"]:
        return "거부", ["이 계정에 등록된 기기가 아님"]

    score = 0
    reasons = []

    if req["health"] != "ok":
        score = score + 40
        reasons.append("기기 보안 상태 이상 (+40)")

    if req["country"] != "KR":
        score = score + 30
        reasons.append("해외에서 접속 (+30)")

    if req["hour"] < 6:
        score = score + 20
        reasons.append("새벽 접속 (+20)")

    if req["mfa"] == False:
        score = score + 20
        reasons.append("MFA 안 함 (+20)")

    if req["count"] >= 20:
        score = score + 30
        reasons.append("대량 조회 (+30)")

    if score >= 50:
        return "거부", reasons

    if score >= 20:
        return "추가확인", reasons

    return "허용", reasons

흐름은 다음과 같았다.

요청
  |
  v
[필수 조건 검사]
  |
  ├─ 어긋남 → 거부
  |
  v
[위험 점수 계산]
  |
  ├─ 50점 이상 → 거부
  ├─ 20점 이상 → 추가확인
  └─ 그 외 → 허용

3.3 요청 한 건 따라가기

요청:

seoyeon
등록 기기 NB-0417
기기 상태 ok
국가 KR
시각 2시
MFA 안 함
40건 조회
단계 검사 요청의 값 결과 누적 점수
1 재직 중인 계정인가 employed = True 통과 0
2 등록 기기인가 NB-0417 통과 0
3 기기 보안 상태 ok 0점 0
4 접속 국가 KR 0점 0
5 새벽인가 2시 +20 20
6 MFA 했는가 False +20 40
7 20건 이상 조회인가 40건 +30 70
8 결정 70점 ≥ 50 거부 70

결과는 다음과 같았다.

(
    "거부",
    [
        "새벽 접속 (+20)",
        "MFA 안 함 (+20)",
        "대량 조회 (+30)"
    ]
)

한 가지 신호만 보고 바로 거부하는 것이 아니라 여러 위험 신호가 겹칠수록 점수가 올라갔다.

모두 정상이면 0점이기 때문에 허용됐다.

3교시 한눈에

하려는 일 코드
요청의 계정 찾기 ACCOUNTS.get(req["user"])
필수 조건으로 바로 거부 return "거부", [이유]
점수 쌓기 score = score + 40
이유 추가 reasons.append()
합계로 결정 50점 이상 거부 · 20점 이상 추가확인
요청 목록 판정 for req in REQUESTS:
결정별 건수 세기 counts[decision] = counts[decision] + 1
이유별 건수 세기 .get(이유, 0) + 1

 

4교시 PDP 와 PEP · ZT 성숙도 점수 · A사 적용 방안 문서

오늘 들어온 일

A사 대표가 보낸 메시지:

「우리 회사의 지금 보안 수준이 어느 정도인지 점수로 알려 주시고, Zero Trust 도입 방안을 문서 하나로 정리해 주세요. 임원 보고에 씁니다.」

이번에는 PDP와 PEP의 역할을 구분하고 직원 정보를 이용해 Zero Trust 성숙도 점수를 계산했다.

왜 필요한가

3교시에서 만든 함수는 결정만 했다.

그 결정을 실제 요청에 적용해 통과시키거나 막는 역할도 필요했고, 그 역할이 PEP였다.

회사 보안 수준도 단순히 좋다 · 나쁘다로 말하는 것보다 점수로 나타내면 무엇부터 개선해야 하는지 확인하기 쉬웠다.

4.1 PDP 와 PEP

PEP

Policy Enforcement Point

PDP가 내린 결정을 실제로 적용하는 곳이다.

요청을 허용하거나 차단하고, 필요한 경우 추가 인증을 요구한다.

예:

  • 프록시
  • 방화벽
  • API 게이트웨이

PDP와 PEP를 나누면 정책을 한 곳에서 수정해도 여러 PEP가 같은 규칙을 사용할 수 있었다.

결정 기록도 한 곳에 모을 수 있었다.

기본 거부

허용 목록에 없는 것은 모두 거부하는 방식이다.

최소권한은 기본적으로 아무 권한도 없는 상태에서 필요한 권한만 추가하는 방식으로 볼 수 있다.

사용자 --요청--> PEP --요청 정보--> PDP
                   ^               |
                   |               |
                   +--- 결정 -------+

허용       → 앱으로 전달
추가확인   → MFA 요구
거부       → 차단하고 로그 기록

이번에 만든 decide_settlement 함수가 PDP 역할을 했다.

4.2 ZT 성숙도 점수

성숙도는 회사가 Zero Trust를 어느 정도 도입했는지를 나타냈다.

이번에는 다섯 항목에 각각 20점을 주고 총 100점으로 계산했다.

항목 만점 계산 5대 원칙
MFA 적용률 20 MFA 사용 직원 ÷ 전체 직원 × 20 ID
기기 보안 점검 비율 20 점검 통과 기기 사용자 ÷ 전체 직원 × 20 Device
최소권한 준수율 20 초과 권한 없는 직원 ÷ 전체 직원 × 20 Application
마이크로 세그멘테이션 20 적용했으면 20, 아니면 0 Network
위험 기반 인증 20 적용했으면 20, 아니면 0 Policy

예를 들어 직원 12명 중 6명이 MFA를 사용한다면 다음처럼 계산할 수 있었다.

round(6 / 12 * 20)

결과는 10점이다.

4.3 파일 만들기

network_zt 폴더 안에서 vim으로 파일을 만들었다.

vim 파일이름

순서는 다음과 같았다.

vim 파일이름
→ i
→ 내용 입력
→ Esc
→ :wq
→ Enter

touch로 파일을 만들고 VS Code에서 작성하는 방법도 사용할 수 있었다.

저장한 내용은 cat으로 확인했다.

cat 파일이름

4교시 한눈에

하려는 일 방법
결정하는 곳 / 막는 곳 PDP / PEP
성숙도 점수 항목당 20점 × 5
허용 목록에 없는 것 기본 거부
새 파일 만들기 vim 또는 touch
저장 내용 확인 cat 파일이름

 

5교시 왜 도커인가 · 이미지와 컨테이너 · 같이 설치하기

왜 필요한가

프로그램을 PC에 직접 설치하면 PC마다 버전과 설정이 달라질 수 있다.

삭제한 뒤에도 기존 파일이나 설정이 남을 수 있다.

이런 차이 때문에 「내 PC에서는 되는데 다른 PC에서는 안 된다」는 문제가 생긴다.

도커는 프로그램과 필요한 파일을 하나로 묶어서 어느 PC에서든 같은 환경으로 실행할 수 있게 해 준다.

[도커 없이]

PC-A: nginx 1.18
PC-B: nginx 1.24
PC-C: nginx 1.18 + 예전 파일

→ PC마다 환경이 다름


[도커 사용]

PC-A
PC-B → nginx:1.28 이미지 사용
PC-C

→ 같은 환경

5.1 도커 없이 설치하는 것과 도커로 실행하는 것

직접 설치하면 버전이나 설정이 서로 달라질 수 있다.

도커에서는 같은 이미지를 받아 실행하기 때문에 여러 PC에서 같은 환경을 만들 수 있었다.

컨테이너를 지울 때도 컨테이너 하나만 지우면 됐다.

5.2 이미지와 컨테이너 · Docker Hub · 엔진

이미지

실행할 프로그램과 필요한 파일을 하나로 묶어 둔 것이다.

이미지는 읽기 전용이다.

nginx:1.28

처럼 이름:태그 형태로 사용했다.

태그는 버전을 나타냈다.

컨테이너

이미지를 실제로 실행한 것이다.

같은 이미지로 여러 개의 컨테이너를 만들 수 있었다.

레지스트리

이미지를 모아 두고 내려받을 수 있게 해 주는 서버이다.

Docker Hub가 대표적인 공개 레지스트리이다.

이미지를 받을 때는 registry-1.docker.io 같은 이름을 DNS로 IP 주소로 바꾸고 인터넷을 통해 이미지를 내려받았다.

Docker Engine

이미지를 받고 컨테이너를 만들어 실행하는 도커의 핵심 프로그램이다.

데몬이라고도 부른다.

Windows에서는 Docker Desktop이 Docker Engine을 설치하고 실행했다.

Docker Desktop은 WSL 2 위에서 엔진을 실행했다.

Docker Client

터미널에서 입력하는 docker 명령이다.

사용자의 명령을 Docker Engine에 전달했다.

Docker Hub
    |
    | pull
    v
nginx:1.28 이미지
    |
    ├── 컨테이너 1
    └── 컨테이너 2

이미지는 한 번 받아 두면 여러 컨테이너를 만들 수 있었다.

컨테이너를 삭제해도 이미지는 남아 있기 때문에 다음에 다시 사용할 수 있었다.

5.3 nginx 기반

이번 실습은 nginx:1.28 이미지를 사용했다.

nginx는 웹 서버 프로그램이다.

브라우저에서 요청이 들어오면 파일을 응답하고 접속 기록을 남긴다.

설정에 따라 다른 서버로 요청을 넘겨 주는 프록시 역할도 할 수 있다.

직접 서버 코드를 만들지 않아도 서버 실행 · 로그 확인 · 종료 등을 연습할 수 있었다.

5.4 Docker 설치

Windows에서는 Docker Desktop을 설치했다.

WSL 2가 없다면 다음 명령으로 설치할 수 있었다.

wsl --install

이미 설치되어 있다면 업데이트할 수도 있었다.

wsl --update

Docker Desktop을 실행한 뒤 Engine running 상태가 될 때까지 기다렸다.

설치 확인은 다음 명령으로 했다.

docker --version

첫 컨테이너는 다음 명령으로 실행했다.

docker run hello-world

이 명령을 실행하면 다음 순서로 동작했다.

docker 명령
    |
    v
Docker Engine
    |
    | 이미지가 없으면
    v
Docker Hub
    |
    | 이미지 다운로드
    v
Docker Engine
    |
    | 컨테이너 생성
    v
hello-world 컨테이너

5교시 한눈에

하려는 일 명령
설치 확인 docker --version
첫 컨테이너 docker run hello-world
내려받은 이미지 docker images
컨테이너 기록 docker ps -a
이미지 이름 이름:태그

 

6교시 nginx 서버 켜고 접속 기록 읽기

왜 필요한가

서버를 켰는데 접속이 안 되는 경우에는 서버가 실제로 실행 중인지, 포트가 연결됐는지, 로그가 남았는지 순서대로 확인해야 한다.

이번에는 docker ps, docker logs, docker exec 등을 사용했다.

컨테이너는 기본적으로 외부에서 바로 접근할 수 없기 때문에 내 PC의 포트와 컨테이너의 포트를 연결해야 했다.

6.1 포트를 연결해야 접속이 된다

브라우저
http://127.0.0.1:8080
        |
        v
내 PC 8080
        |
        | -p 8080:80
        v
컨테이너 nginx 80

nginx는 컨테이너 안의 80번 포트를 사용했다.

내 PC의 8080번으로 들어온 요청을 컨테이너의 80번으로 넘기도록 연결했다.

-p 내PC포트:컨테이너포트

이런 방식은 포트 포워딩이라고도 한다.

포트를 연결하지 않으면 컨테이너가 실행 중이어도 브라우저에서 접속할 수 없다.

주소 읽기

127.0.0.1

내 PC 자신을 가리킨다.

0.0.0.0

이 PC가 가진 모든 주소를 의미한다.

80/tcp

80번 포트를 TCP 방식으로 사용한다는 뜻이다.

6.2 접속 기록 한 줄 읽기

nginx는 요청을 처리할 때마다 로그를 한 줄씩 남겼다.

예:

172.17.0.1 - - [19/Oct/2026:14:31:05 +0000] "GET / HTTP/1.1" 200 615
부분 뜻
172.17.0.1 요청을 보낸 쪽의 주소
[19/Oct/2026:14:31:05 +0000] 요청을 받은 시각
"GET / HTTP/1.1" 요청 방식 · 주소 · 프로토콜
200 응답 번호
615 응답 크기

200은 요청이 성공했다는 뜻이다.

404는 요청한 파일이나 주소가 없다는 뜻이다.

서버를 실행한 직후 docker logs를 확인하면 접속 기록이 없을 수도 있다.

아직 브라우저에서 요청을 보내지 않았기 때문이다.

docker run
   |
   v
docker logs
→ 시작 메시지만 있음
   |
   v
브라우저 접속
   |
   v
docker logs
→ GET 요청 기록 생성

브라우저가 favicon.ico를 요청했는데 파일이 없으면 404가 나올 수 있었다.

이 경우는 정상적인 상황이라 넘어갔다.

새로고침 후 304가 나오기도 했다.

304는 바뀐 내용이 없으니 저장해 둔 화면을 그대로 사용하라는 의미이다.

6.3 Docker 명령

nginx 서버를 실행했다.

docker run -d --name web -p 8080:80 nginx:1.28

실행 중인 컨테이너를 확인했다.

docker ps

로그를 확인했다.

docker logs web

컨테이너 내부에 들어갔다.

docker exec -it web sh

나올 때는 다음 명령을 사용했다.

exit

컨테이너를 멈췄다.

docker stop web

멈춘 컨테이너를 삭제했다.

docker rm web
명령 하는 일
docker run -d --name web -p 8080:80 nginx:1.28 서버 실행
docker ps 실행 중인 컨테이너 확인
docker logs web 로그 확인
docker exec -it web sh 컨테이너 안으로 들어가기
docker stop web 컨테이너 정지
docker rm web 컨테이너 삭제

-d는 컨테이너를 백그라운드로 실행했다.

--name은 컨테이너 이름을 지정했다.

-p는 포트를 연결했다.

-it는 컨테이너 안의 터미널을 직접 사용할 수 있게 했다.

6교시 한눈에

하려는 일 명령
서버 켜기 docker run -d --name 이름 -p 내PC포트:컨테이너포트 이미지:태그
켜진 것 보기 docker ps
끈 것까지 보기 docker ps -a
로그 보기 docker logs 이름
컨테이너 안에 들어가기 docker exec -it 이름 sh
컨테이너 끄기 docker stop 이름
컨테이너 삭제 docker rm 이름
실행 중인 상태로 삭제 docker rm -f 이름

 

7교시 내 페이지 연결 · 두 서버 · 올리기

왜 필요한가

컨테이너 안에서 직접 수정한 파일은 컨테이너를 삭제하면 같이 사라진다.

웹 페이지의 index.html이나 설정 파일처럼 계속 보관해야 하는 파일은 내 PC에 두고 컨테이너가 읽도록 연결하는 것이 좋다.

서버를 여러 개 실행할 때는 서로 다른 포트를 사용하면 한 PC에서도 여러 서버를 띄울 수 있다.

읽기 전용으로 연결하면 컨테이너가 내 파일을 수정하지 못하게 할 수 있다.

내 폴더를 컨테이너에 연결

Git Bash에서는 다음과 같이 실행했다.

MSYS_NO_PATHCONV=1 docker run -d --name 이름 -p 포트:80 -v "$(pwd)/폴더:/usr/share/nginx/html:ro" nginx:1.28

-v를 사용해 내 PC의 폴더와 컨테이너의 폴더를 연결했다.

내 PC 폴더
      |
      | -v
      v
/usr/share/nginx/html
      |
      v
nginx

:ro는 read only를 뜻했다.

컨테이너가 연결된 파일을 읽을 수는 있지만 수정하지는 못했다.

최소권한과 비슷한 방식으로 볼 수 있었다.

서버 두 대 실행

한 PC에서 서버를 두 개 실행하려면 내 PC 쪽 포트를 다르게 연결했다.

내 PC 8080 → 컨테이너 1의 80
내 PC 8081 → 컨테이너 2의 80

컨테이너 안의 nginx는 둘 다 80번을 사용할 수 있었다.

바깥에서 접근할 때 사용하는 내 PC의 포트만 다르게 지정했다.

브라우저에서는 다음처럼 각각 접근할 수 있었다.

http://127.0.0.1:8080
http://127.0.0.1:8081

여러 컨테이너를 한 번에 정리할 수도 있었다.

docker rm -f 이름1 이름2

7교시 한눈에

하려는 일 명령
내 폴더를 서버에 연결 -v "$(pwd)/폴더:/usr/share/nginx/html:ro"
컨테이너 안에서 바꾼 파일 컨테이너를 지우면 같이 사라짐
서버 두 대 실행 내 PC 포트를 8080 · 8081처럼 다르게 연결
읽기 전용 연결 :ro
한꺼번에 정리 docker rm -f 이름1 이름2

 

 

 

오늘은 도커를 깔고 해보는 과정을 가졌는데, 오랜만에 해본 것 같아요

사실 딱 한번..? 두번 밖에 안해봤는데 자세하게 알려주셔서 그런가 좋았습니다.

오늘 사실 너무 피곤해요,,, 어제 어디 놀러갔다왔는데 진짜 피곤... 하지만 ?? 수업은 열심이 들었다...

그럼 아됴

안녕하세요1!!!!!!

벌써 금요일입니다.

정말 일주일이 정말 빠르게 지나간 것 같아요.

그럼 모닝 30 레츠고.

1. 왜 이걸 하는지 찾아봅니다

1.1 서버에 접속하면 VS Code 가 없습니다. 보안 담당자는 서버의 설정 파일을 어떻게 고칠까요?

>

보안 담당자는 SSH로 리눅스 서버에 원격 접속한 뒤 vim이나 nano 같은 터미널 기반 텍스트 편집기를 사용하여 설정 파일을 수정한다. vim은 GUI가 없는 서버에서도 사용할 수 있고, 별도의 그래픽 편집기를 설치하지 않아도 설정 파일을 관리할 수 있어 서버 운영에 유용하다. 예를 들어 sudo vim /etc/ssh/sshd_config 명령으로 SSH 서버 설정 파일을 열어 수정할 수 있다.

vim 의 모드와 키를 익힙니다

왜 중요한가 — vim 은 처음 열면 글자를 쳐도 입력되지 않아서 많은 사람이 여기서 막힙니다. 모드 세 개와 저장 · 종료 키만 알면 서버에서 파일을 고치고 나올 수 있습니다.

vim(빔 · 터미널 안에서 쓰는 글 편집기)은 마우스 없이 키보드로만 씁니다. 키가 하는 일을 정하는 상태, 즉 모드(mode)가 세 가지 있습니다.

모드들어가는 법이때 키가 하는 일화면에서 보이는 것

일반 모드 (Normal mode · 명령을 내리는 상태) vim 을 열면 처음 여기 · 다른 모드에서 Esc 키가 명령이 된다 — 이동 · 지우기 · 복사 왼쪽 아래가 비어 있다
입력 모드 (Insert mode · 글자를 입력하는 상태) 일반 모드에서 i 키가 글자로 입력된다 왼쪽 아래 -- INSERT --
명령줄 모드 (Command-line mode · 저장 · 종료 명령을 치는 상태) 일반 모드에서 : 저장 · 종료 · 바꾸기 명령을 친다 왼쪽 아래 : 와 친 글자

아래 키는 모두 일반 모드에서 칩니다. : 로 시작하는 명령은 끝에 Enter 를 누릅니다.

키하는 일

i 입력 모드로 들어간다 (커서 앞에 글자가 들어간다)
Esc 일반 모드로 돌아온다
:w 저장한다 (write)
:q 나간다 (quit). 고친 뒤 저장하지 않았으면 나가지지 않는다
:wq 저장하고 나간다
:q! 저장하지 않고 강제로 나간다. 고친 내용은 사라진다
dd 커서가 있는 줄 하나를 지운다
yy · p 줄을 복사한다 · 커서 아래 줄에 붙여 넣는다
u 방금 한 것을 되돌린다
/단어 단어를 찾는다. n 을 누르면 다음 것으로 간다
gg · G 맨 위 줄로 · 맨 아래 줄로 간다
:%s/옛/새/g 파일 전체에서 옛 을 새 로 바꾼다

방향키로 커서를 움직여도 됩니다.

키가 먹지 않을 때 — 아래 둘 중 하나입니다.

  • 키보드가 한글 상태이면 i 가 ㅑ 로 입력되어 아무 일도 일어나지 않습니다. 한/영 키로 영문으로 바꿉니다.
  • 입력 모드(-- INSERT --)에서 :wq 를 치면 글자로 입력됩니다. 먼저 Esc 를 누릅니다.

어떻게 해도 못 나가겠으면 Esc 를 두 번 누르고 :q! Enter 를 입력합니다.


오늘의 순서

교시 무엇
2교시 클라우드 · SaaS · 회사 방화벽이 못 보는 접속
3교시 망 구성도 읽고 고치기 · DMZ
4교시 구역 규칙을 판정하는 코드 읽기와 만들기
5교시 지연 · 지터 · 패킷 손실
6교시 코드로 세 숫자 계산하고 판정하기
7교시 tracert 로 느려진 구간 찾기 · 5일 차 품질 진단 리포트

 

2교시 — 클라우드 · SaaS · 회사 방화벽이 못 보는 접속

왜 필요한가

서버와 업무 도구가 클라우드로 옮겨 가면서 어디까지 업체가 관리하고 어디부터 내가 관리하는지가 서비스마다 달라졌다.

내가 관리하는 범위가 좁을수록 사용할 수 있는 보안 설정도 줄어들었다.

그래서 서비스를 확인할 때는 먼저 IaaS, PaaS, SaaS 중 어떤 형태인지 구분해야 했다.

직원이 집에서 SaaS 에 바로 접속하면 회사 방화벽을 지나지 않았다.

이 경우 회사 방화벽 로그에는 접속 기록이 남지 않았고, 보안팀은 SaaS 서비스가 제공하는 로그인 기록과 활동 기록을 확인해야 했다.

2.1 클라우드 서비스의 세 형태

클라우드

내 건물이 아니라 업체의 서버를 인터넷으로 빌려 쓰는 방식이었다.

IaaS

Infrastructure as a Service

서버와 저장소, 네트워크를 빌리는 형태였다.

운영체제 설치 · 패치 · 보안 설정은 직접 관리했다.

PaaS

Platform as a Service

운영체제와 실행 환경까지 업체가 관리하는 형태였다.

회사는 코드와 데이터를 관리했다.

SaaS

Software as a Service

완성된 서비스를 계정만 받아 사용하는 형태였다.

회사는 계정 · 권한 · 데이터를 관리했다.

형태 내가 맡는 것 방화벽 규칙을 직접 걸 수 있나
IaaS 운영체제 · 보안 설정 · 코드 · 데이터 걸 수 있다
PaaS 코드 · 데이터 업체가 정한 범위 안에서만 걸 수 있다
SaaS 계정 · 권한 · 데이터 걸 자리가 없다

IaaS → PaaS → SaaS 로 갈수록 내가 직접 관리할 수 있는 범위가 줄어들었다.

실제 서비스로 보면 다음과 같았다.

형태 대표 서비스 회사가 하는 일의 예
IaaS AWS EC2 · Google Compute Engine · Azure Virtual Machines 가상 서버를 만들고 운영체제와 보안 설정을 관리했다
PaaS Vercel · Heroku · Azure App Service 코드를 올리고 환경 설정과 데이터를 관리했다
SaaS Google Docs · Microsoft 365 · Slack 직원 계정 · 권한 · 공유 범위를 관리했다

한 회사에서 세 가지 형태를 함께 사용하는 경우도 많았다.

예를 들면 회사 홈페이지는 Vercel, 사내 DB는 AWS EC2, 업무 문서는 Google Docs 를 사용할 수 있었다.

2.2 회사 방화벽을 지나지 않는 접속

예전에는 다음과 같은 경로로 인터넷에 접속했다.

사내 PC → 사내망 → 회사 방화벽 → 인터넷

모든 접속이 회사 방화벽을 지나기 때문에 한 곳에서 기록하고 통제할 수 있었다.

재택근무에서는 다음과 같이 접속할 수도 있었다.

집 PC → 인터넷 → SaaS 서비스

이 경우 회사 망과 회사 방화벽을 지나지 않았다.

따라서 회사 방화벽 로그에는 해당 접속이 남지 않았다.

가시성

가시성(visibility)은 무슨 일이 일어나는지 보안팀이 확인할 수 있는 정도를 뜻했다.

접속이 회사 방화벽을 지나지 않으면 가시성이 떨어졌다.

이때는 SaaS 서비스가 남기는 기록을 확인해야 했다.

SaaS 에서는 주로 두 가지 기록을 볼 수 있었다.

  • 로그인 기록: 누가 · 언제 · 어느 IP 에서 로그인했는지
  • 활동 기록: 로그인한 뒤 무엇을 열람하거나 다운로드했는지

직원이 집에서 Google Docs 나 Slack 에 로그인하면 회사 방화벽을 지나지 않았다.

따라서 방화벽 로그가 아니라 Google Workspace 같은 서비스의 로그인 기록과 활동 기록을 확인해야 했다.

퇴사 예정자 계정이 새벽에 낯선 IP 에서 로그인했다면 계정 도용을 먼저 의심할 수 있었다.

2교시 한눈에

하려는 일 보는 곳
서비스 형태 구분 운영체제까지 직접 관리하면 IaaS · 코드만 관리하면 PaaS · 계정만 관리하면 SaaS
사내에서 접속한 기록 회사 방화벽 로그
집 · 외부에서 SaaS 에 접속한 기록 SaaS 의 로그인 기록
조치 보고 확인된 것과 확인하지 못한 것을 나눠 작성했다

 

3교시 — 망 구성도 읽고 고치기 · DMZ

왜 필요한가

고객사 환경을 처음 확인할 때는 먼저 망 구성도를 확인했다.

구성도를 보면 어떤 서버가 인터넷에 공개되어 있고 어떤 서버가 내부망에 있는지 확인할 수 있었다.

웹 서버 같은 공개 서버가 내부망 안에 있는지 별도의 DMZ 에 있는지에 따라 사고가 발생했을 때 피해 범위가 달라질 수 있었다.

3.1 구성도를 읽는 순서

구성도

장비와 장비 사이의 연결을 그린 그림이었다.

구역

방화벽이 네트워크를 나눈 영역이었다.

이번에는 다음 세 구역을 사용했다.

  • outside : 인터넷
  • DMZ
  • inside : 내부망

DMZ

Demilitarized Zone

외부에 공개해야 하는 서버만 따로 배치한 중간 구역이었다.

웹 서버가 공격을 받더라도 내부 서버로 접근하려면 방화벽을 한 번 더 지나야 했다.

도식에서 사용한 기호

모양 뜻
INTERNET 인터넷
FW 방화벽
INSIDE 내부망
( WEB ) 해당 구역에 있는 서버
WEB 웹 서버
DB 데이터베이스 서버
──── 연결선
┬ · │ · └ 연결이 갈라지는 부분

구성도는 왼쪽에서 오른쪽으로 선을 따라 읽었다.

INTERNET ──── FW ──── INSIDE ( PC · FILE )

이 구성은 인터넷에서 오는 통신이 방화벽을 지나 내부망으로 들어가고, 내부망에는 직원 PC 와 파일 서버가 있다는 뜻이었다.

공개 서버는 없었다.

연결이 갈라지는 구성은 다음처럼 읽었다.

INTERNET ──── FW ──┬── DMZ    ( MAIL )
                   └── INSIDE ( PC )

방화벽에서 길이 두 개로 나뉘었고, 메일 서버는 DMZ 에 있었으며 직원 PC 는 내부망에 있었다.

공개 서버가 내부 서버와 같은 구역에 있다면 DMZ 가 없는 구성이었다.

방화벽의 개수만 보고 DMZ 여부를 판단하면 안 됐다.

회사 홈페이지 서버나 메일 서버처럼 인터넷에서 접속해야 하는 서버는 DMZ 에 두고, DB 서버나 파일 서버는 내부망에 두는 방식으로 구성했다.

클라우드에서도 같은 원칙을 적용할 수 있었다.

예를 들어 AWS EC2 에 만든 웹 서버는 443번 포트만 외부에 열고, DB 서버는 인터넷에서 직접 접근할 수 없도록 구성할 수 있었다.

경보와 로그 읽기

경보(alert)는 보안 장비가 이상한 통신을 발견했을 때 발생시키는 알림이었다.

로그는 다음 순서로 읽었다.

번호 → 시각 → 출발지 → 목적지 → 포트 → 결과

permit은 허용을 의미했고 deny는 차단을 의미했다.

3교시 한눈에

하려는 일 보는 곳
공개 서버가 어느 구역인지 구성도에서 WEB 이 들어 있는 구역
DMZ 가 있는지 WEB 과 DB 가 다른 구역에 있는지
해킹 시 번지는 경로 WEB → DB 사이의 방화벽
로그가 이상한지 출발지 → 목적지가 가면 안 되는 경로인지
고친 구성도 남기기 ASCII 로 구성도를 작성했다

 

4교시 — 구역 규칙을 판정하는 코드 읽기와 만들기

왜 필요한가

고객이 요구사항대로 방화벽 규칙이 설정됐는지 확인해 달라고 하면 눈으로만 확인하는 것보다 코드로 요청을 넣어 판정하는 것이 정확했다.

이전에는 IP 주소와 포트를 기준으로 방화벽 규칙을 판정했고, 이번에는 outside · DMZ · inside 같은 구역을 이용해 규칙을 판정했다.

값 두 개를 리턴하고 받기

함수에서는 값을 쉼표로 이어 두 개 이상 리턴할 수 있었다.

def two():
    return "permit", 1

a, n = two()

print(a, n)
print(two())

결과는 다음과 같았다.

permit 1
('permit', 1)

값을 변수 두 개로 받으면 각각 나눠서 저장됐다.

변수 하나로 받으면 튜플 하나로 저장됐다.

기본 정책

기본 정책은 규칙에 일치하는 항목이 없을 때 사용하는 기본 동작이었다.

이번 코드에서는 같은 구역끼리의 통신, 내부망에서 출발하는 통신, 인터넷으로 나가는 통신은 허용하고 나머지는 차단하도록 했다.

튜플

규칙 하나는 다음과 같은 튜플로 표현했다.

(1, "outside", "DMZ", 443, "permit")

튜플 안의 값을 번호로 꺼낼 수도 있었다.

rule[0]
rule[4]

rule[0]은 규칙 번호였고 rule[4]는 동작이었다.

한 번에 여러 변수로 나눠 받을 수도 있었다.

no, r_src, r_dst, r_port, action = rule

4교시 한눈에

하려는 일 코드
규칙 하나가 요청과 맞는지 match_rule(rule, src, dst, port)
규칙표를 위에서부터 판정 judge(src, dst, port)
허용되는 포트만 모으기 allowed_ports(src, dst, ports)
값 두 개 리턴 · 받기 return a, b · x, y = f()

 

5교시 — 지연 · 지터 · 패킷 손실

왜 필요한가

사용자가 인터넷이 느리다고 말하는 것만으로는 정확한 원인을 확인하기 어려웠다.

따라서 느린 현상을 숫자로 표현해야 했다.

이번에는 다음 세 가지를 확인했다.

  1. 지연
  2. 지터
  3. 패킷 손실

5.1 세 가지 숫자

지연

Latency

패킷을 보낸 뒤 응답이 돌아올 때까지 걸리는 시간이었다.

실무에서는 왕복 시간인 RTT를 주로 확인했다.

단위는 ms를 사용했다.

지터

Jitter

응답 시간이 얼마나 일정하지 않은지를 나타내는 값이었다.

이번 수업에서는 이웃한 두 응답 시간의 차이의 평균으로 계산했다.

패킷 손실

Packet Loss

보낸 패킷 가운데 응답이 오지 않은 비율이었다.

손실된 데이터는 다시 전송해야 했다.

예를 들어 응답 시간이 다음과 같았다.

50ms
52ms
120ms
48ms

평균은 67.5ms였다.

평균만 보면 크게 문제가 없어 보일 수 있었지만 세 번째 응답이 120ms로 크게 튀었다.

화상회의나 음성 통화 같은 실시간 서비스에서는 패킷이 일정한 간격으로 도착해야 하기 때문에 평균 지연이 낮더라도 지터가 크면 끊김이 발생할 수 있었다.

지연이 일정하게 큰 경우에는 조금 늦게 들릴 수 있었고, 지터나 손실이 크면 음성이나 화면이 끊길 수 있었다.

대용량 파일 다운로드가 느린 경우에는 지연보다는 대역폭을 먼저 확인했다.

온라인 게임에서 사용하는 「핑 30」이라는 표현도 RTT가 약 30ms라는 뜻이었다.

5.2 ping 으로 직접 측정하기

Windows에서는 다음 명령을 사용했다.

ping -n 10 8.8.8.8

10번의 요청을 보내 각각의 응답 시간을 확인했다.

결과에서는 다음 항목을 확인했다.

  • 각각의 응답 시간
  • 평균 지연
  • 패킷 손실
  • 최소 시간
  • 최대 시간

응답이 없는 경우에는 요청 시간이 만료됐다는 메시지가 나왔고, 이를 패킷 손실 한 번으로 볼 수 있었다.

5교시 한눈에

확인하는 것 방법
지연 응답 시간의 평균
지터 이웃한 두 값의 차이의 평균
손실 못 받은 개수 ÷ 보낸 개수 × 100
직접 측정 ping -n 10 주소

 

6교시 — 코드로 세 숫자 계산하고 판정하기

왜 필요한가

회선이 여러 개이고 측정값이 많아지면 직접 계산하기 어려웠다.

5교시에서 계산한 지연 · 지터 · 손실을 코드로 계산하도록 만들었다.

계산한 숫자에 기준을 적용해 화상회의에 적합한 회선인지도 판정했다.

abs()

abs()는 숫자의 절댓값을 구했다.

print(abs(5))
print(abs(-5))
print(abs(31 - 30))
print(abs(29 - 31))

결과는 다음과 같았다.

5
5
1
2

지터를 계산할 때 이웃한 두 값 중 어느 값이 더 큰지 신경 쓰지 않고 차이를 계산할 수 있었다.

독스트링

함수 이름 아래에 따옴표 세 개로 설명을 작성하면 함수 전체를 설명하는 독스트링을 만들 수 있었다.

def average(nums):
    """응답 시간 리스트의 평균을 구한다.

    입력: 응답 시간 리스트 nums
    리턴: 평균 값
    """

    return sum(nums) / len(nums)

help()를 사용하면 독스트링을 확인할 수 있었다.

print(average([30, 31, 29]))
help(average)

주석은 코드 한 줄을 설명하는 데 사용했고, 독스트링은 함수 전체의 역할 · 입력 · 반환값을 설명하는 데 사용했다.

지터 계산

다음과 같은 반복 범위를 사용할 수 있었다.

range(1, len(got))

0번째 값에는 바로 앞 값이 없기 때문에 1번부터 반복했다.

현재 값과 바로 앞 값을 이용해 차이를 계산했다.

got[i]
got[i - 1]

응답이 없는 ping 값은 None으로 표현했다.

None

응답이 있는 값만 사용하려면 다음처럼 확인했다.

if v != None:
    got.append(v)

화상회의 판정 기준

이번 수업에서 사용한 기준은 다음과 같았다.

항목 기준
평균 지연 150ms 이하
지터 30ms 이하
손실률 1% 이하

세 기준을 모두 만족해야 적합으로 판정했다.

하나라도 기준을 넘으면 부적합으로 판정했다.

어떤 값이 기준을 넘었는지 확인하면 문제의 원인도 좁힐 수 있었다.

값 세 개를 한 번에 리턴할 수도 있었다.

return delay, jitter, loss

받을 때도 세 개의 변수로 나눠 받을 수 있었다.

delay, jitter, loss = measure(...)

여러 원인을 한 줄로 합칠 때는 join()을 사용할 수 있었다.

", ".join(reasons)

예를 들어 다음 리스트가 있다면

["지연", "지터"]

다음과 같은 문자열이 만들어졌다.

지연, 지터

6교시 한눈에

하려는 일 코드
응답이 있는 값만 모으기 if v != None: got.append(v)
이웃한 차이 계산 abs()
세 기준을 모두 확인 비교식을 and로 연결
여러 원인을 한 줄로 만들기 ", ".join(reasons)

 

7교시 — tracert 로 느려진 구간 찾기 · 5일 차 품질 진단 리포트

왜 필요한가

ping으로 지연이 크다는 것을 확인했다면 다음에는 어느 구간에서 지연이 증가하는지 찾아야 했다.

문제가 회사 내부인지 통신사인지 SaaS 업체인지에 따라 문제를 해결해야 하는 주체가 달라졌다.

이때 tracert를 사용할 수 있었다.

7.1 tracert 로 느려진 구간 확인하기

tracert는 목적지까지 거쳐 가는 장비를 순서대로 보여 주고 각 장비까지의 응답 시간을 확인할 수 있는 명령이었다.

tracert google.com

각 장비 하나를 홉이라고 불렀다.

내 PC
  ↓
1번 홉 : 공유기
  ↓
2번 홉 : 통신사 장비
  ↓
3번 홉 : 다른 라우터
  ↓
...
  ↓
목적지 서버

각 홉의 시간은 바로 앞 홉에서 그 장비까지 걸린 시간이 아니었다.

내 PC 에서 해당 장비까지 갔다가 돌아오는 왕복 시간이었다.

tracert 결과 읽는 방법

시간이 처음 크게 증가한 홉을 찾았다.

그 이후 홉도 계속 높은 값을 유지하면 처음 증가한 홉과 바로 앞 홉 사이의 구간에서 문제가 발생했을 가능성이 있었다.

예를 들어 다음과 같았다.

1번 홉     1ms
2번 홉     3ms
3번 홉     5ms
4번 홉    80ms
5번 홉    85ms
6번 홉    82ms

3번 홉까지는 정상이었지만 4번 홉부터 지연이 크게 증가했다.

따라서 3번과 4번 사이의 구간을 의심할 수 있었다.

반대로 한 홉에서만 시간이 크게 증가했다가 다음 홉에서 다시 낮아진다면 실제 네트워크 장애가 아닐 수도 있었다.

1번 홉     1ms
2번 홉     3ms
3번 홉   100ms
4번 홉     7ms
5번 홉     8ms

3번 장비가 tracert 응답만 늦게 보낸 것일 수 있었다.

실제 패킷 전달 자체는 정상일 가능성이 있었다.

7.2 순서대로 좁혀 가는 진단

SaaS 접속이 느리다는 문제가 발생했다면 다음 순서로 확인할 수 있었다.

  1. ping으로 지연 · 지터 · 손실을 확인했다.
  2. tracert로 어느 구간에서 지연이 증가하는지 확인했다.
  3. 문제가 회사 내부라면 방화벽 · 프록시 로그를 확인했다.
  4. 회사 내부가 정상이라면 통신사 또는 SaaS 업체에 측정 결과와 함께 확인을 요청했다.
  5. SaaS 제공자의 상태 페이지에 장애 공지가 있는지도 확인했다.

이 과정을 통해 단순히 「인터넷이 느리다」라고 판단하는 것이 아니라 지연 · 지터 · 손실을 숫자로 확인하고, tracert를 이용해 문제가 발생한 구간까지 좁힐 수 있었다.

 

 

 

---

 

와..드디어 금요일이 찾아왔어요,,

내일은 여행을 가기때문에 집에가면 바로 짐싸구 호다닥 자야될 것 같아요

힘든 수업 와중에 소소한 즐거움,,^____^

그럼 아됴

+ Recent posts