728x90

서비스의 세계에서 모든 것은 자동화, 데몬화 해두는 것이 좋습니다. 
그렇지만 어떤 이유로든 일회성, ad-hoc으로 작업해야 할 경우도 있기 마련입니다. 

서버 시간의 동기화도 마찬가지입니다. 
정석은 ntpd(ntp 데몬)을 활성화하여 지속적으로 동기화 하는 것입니다. 
다만 그렇지 못한 상황에서는 어떻게 하면 될까요?


ntpdate를 이용한 일회성 업데이트

CentOS 기준으로 /sbin 폴더 하위에 ntpdate 바이너리가 존재합니다. 
이를 이용하여 ntp 서버를 지정하면 일회성으로 서버의 시간을 동기화 해줍니다. 

sudo /sbin/ntpdate 202.28.116.236

명령을 수행하면 서버의 시간 정보를 지정된 NTP 서버 IP로부터 동기화를 하여 맞추게 됩니다. 
서버 시간 정보에 따라 어떤 조정을 했는지를 결괏값으로 알려줍니다.

// 서버 시간이 빠르거나 느린경우
ntpdate[86379]: step time server 202.28.116.236 offset -51.136374 sec
ntpdate[56913]: step time server 202.28.116.236 offset 55.014698 sec

// 미세한 차이로 인해 조정한 경우
ntpdate[46062]: adjust time server 202.28.116.236 offset 0.000091 sec

 

ntp 서버 정보는 어디에서?

인프라 규모가 꽤 큰경우 자체 NTP 서버를 운영할 때가 많습니다. 
하지만 영세하거나 얹혀서 서비스 하고 있는 경우 변변한 NTP 서버가 없기 마련입니다. 
Microsoft, Google 같은 곳에서도 NTP를 제공하긴 하지만
다음과 같은 비영리 단체를 통해서 NTP 서버를 공급(?) 받는 것도 좋습니다. 

 

pool.ntp.org: the internet cluster of ntp servers

Packet is awesome. When we started planning our recent unplanned server move, we investigated options for having not one, but two sites, for the “hub” systems for the NTP Pool. With 4000 NTP servers and hundreds of millions of clients using the system,

www.ntppool.org

해당 페이지에서 아시아쪽 서버를 탐색해보면 다음과 같은 다양한 지역 서버가 나옵니다. 
이 글을 쓰는 2022년 7월 12일 기준으로, 아시아 지역에는 336대의 NTP 서버가 운영중입니다. 

kr.pool.ntp.org 라는 주소를 쓰거나
가이드에 나온 것처럼 ntp.conf 파일을 정의해서 사용하면 되겠습니다!

728x90
728x90

메일링을 하다보면 스팸 처리를 신경쓰지 않을 수 없습니다.
사용자들에게 중요한 메일을 발송하거나 안내 메일을 보냈는데
메일이 스팸함에 들어가 버리면 무척 곤란하겠죠?

스팸 처리와 관련하여 메일을 수신한 서버가 발신자를 검증하는 방법은 여러가지입니다. 
그 중에서도 가장 기본적인 것이 SPF 레코드입니다.

SPF 레코드란?
SPF는 Sender Policy Framework의 약어로 특정 도메인에서 이메일을 보낼 수 있도록 승인된 모든 서버를 열거하는 DNS TXT 레코드의 한 가지 유형입니다.
(출처 : https://www.cloudflare.com/ko-kr/learning/dns/dns-records/dns-spf-record/)

 

수신된 메일 원문/헤더 확인하기

가령 네이버 메일을 이용하여 구글 메일 주소로 메일을 발송하면
구글 메일 서버가 정말로 네이버 메일 서버를 통해 발송된 것인지
확인하기 위해 참조하는 정보가 SPF 레코드라 보시면 됩니다. 
실제로 한 번 보내보도록 하겠습니다. 

네이버에서 보낸 메일을 수신한 Gmail 수신함

Gmail로 수신된 네이버에서 보낸 메일의 헤더 정보를 살펴보겠습니다. 
우측의 More 메뉴를 누르면 `Show Original` 이라는 옵션이 보입니다. 
이것을 눌러 메일 헤더 정보를 살펴보겠습니다. 

화면 하단에는 Raw 헤더 정보가 존재하고, 상단에는 위 그림처럼 
메일에 대하여 SPF, DKIM, DMARC 검증 요약 결과가 출력됩니다. 
SPF 검증이 126.209.224.234 IP 로 확인되었다고 하는데 
이 과정을 한번 살펴보도록 하겠습니다. 

 

Raw 헤더 정보에서 `Return-path` 확인하기

SPF 검증을 위해서는 메일을 보낸 도메인의 DNS를 통해 SPF 값을 확인해야 합니다. 
이 때 사용되는 도메인이 꼭 메일 주소의 도메인과 같지 않을수도 있습니다. 
수신 서버는 메일 헤더 정보에서 `Return-path`를 보고 SPF를 조회할 도메인을 결정합니다.
네이버의 경우 메일 주소의 도메인과 동일한 도메인을 쓰긴 하네요. 

Return-Path의 도메인을 SPF 검증에 사용합니다.

 

SPF 정보 확인하기

구글 메일 서버는 Return-Path에 지정된 naver.com 으로부터 SPF 정보를 획득합니다. 
dig을 이용해서 naver.com의 SPF 정보를 조회해 보겠습니다. 
참고로 SPF는 리소스 레코드 타입으로도 규격이 존재하긴 하지만
오늘날 실제로는 TXT 레코드의 값으로 지정하는 것이 일반적입니다. 

% dig naver.com TXT +short | grep spf
"v=spf1 ip4:111.91.135.0/27 ip4:125.209.208.0/20 ip4:125.209.224.0/19 ip4:210.89.163.112 ip4:210.89.173.104/29 ip4:117.52.140.128/26 ~all"

`v=spf`로 시작하는 이 값은 유효한 메일 발신 서버를 알려주는 역할을 수행합니다. 
`ip4`로 지정된 주소에서 메일이 발신되었는지를 비교한다 생각하시면 되겠죠? 
실제로 include 등의 지시자를 통해 다른 도메인에서 SPF 정보를 참조하는 것도 가능하지만 
네이버의 경우에는 그렇게 구성되어 있지는 않은 것으로 확인됩니다. 

자, 그러면 이제 메일 헤더에서 발신 서버의 주소를 확인해 보겠습니다.
위의 이미지에도 있지만 친절하게 한번 더 보겠습니다. 

 

발신서버 확인하기

발신 서버 주소는 메일 헤더에서 `Received` 값을 확인하면 됩니다. 
제가 보낸 메일은 cvsmtppost019.nm.naver.com 서버를 통해 발송되었고 
이 서버 도메인을 질의해보면 125.209.224.234 주소가 나오는 것으로 보입니다. 

% dig cvsmtppost019.nm.naver.com +short
125.209.224.210
125.209.224.234

SPF 레코드의 값들 중 `ip4:125.209.224.0/19` 에 매칭된다는 것을 확인할 수 있겠죠?
이 과정을 통해 구글 메일 서버는 적법한 서버를 통해 메일이 발송되었고 
스팸 처리를 하지 않아도 된다고 판단한 후, 제 구글 메일의 inbox 에 메일을 넣어주었다고 보시면 되겠습니다. 


메일은 구닥다리처럼 보이지만 여전히 광범위하게 사용됩니다. 
메일은 지금도 진화하고 있고 앞으로도 진화할 겁니다.
따라서 메일에 대해 잘 이해하고 활용하는 것이
여러분, 혹은 여러분이 속한 회사의 비즈니스에 중요하다는 것은 명확해 보입니다!

 

 

최고의 보안을 제공되는 NordVPN을 만나보세요 | NordVPN

최고의 VPN을 즐겨보세요. 악성 소프트웨어, 광고, 추적기를 차단하고 강력한 비밀번호를 생성, 저장하도록 도와드립니다. 암호화된 클라우드로 파일을 보호하세요.

nordvpn.com


본 포스팅은 제휴마케팅을 통해
소정의 수수료를 지급받을 수 있습니다. 

728x90
728x90

서버의 환경을 해치지 않으면서
이미지로 공급되는 어플리케이션간의 통신을 
구현해야 하는 경우가 많이 있습니다. 

외부로 노출은 nginx로 제한하고
실제 각 어플리케이션 접근을
nginx의 location 지시자를 이용하는 경우가 
대표적인 시나리오입니다. 

사용자에 대한 노출은 nginx endpoint 만하고 싶다면?

docker-compose로 다수 컨테이너 구동하기

이 구성을 위해서는 docker-compose를 이용해서 
복수의 컨테이너를 하나의 설정으로 만들어
컨테이너를 배포하는 것이 눈에 잘 들어오고 편리합니다. 

속도 측정을 위한 오픈소스 어플리케이션인
librespeed를 별도의 컨테이너로 띄워두고
nginx도 별도로 구동하기 위해서는 
다음과 같은 설정을 활용할 수 있습니다. 

version: "2"
services:
  nginx:
    container_name: nginx-test
    image: nginx
    ports:
    - 443:443
  speedtest:
    container_name: speedtest
    image: adolfintel/speedtest
    environment:
    - MODE=standalone
    ports:
    - 80:80

nginx의 설정파일은 아래와 같습니다.

upstream speedtest {
    server speedtest:80;
}

server {
    listen      443 ssl;
    server_name example.com;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    ssl_certificate /etc/nginx/cert/fullchain.crt;
    ssl_certificate_key /etc/nginx/cert/private.key;

    access_log  /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log debug;

    location / {
        proxy_pass http://speedtest;
    }
}

컨테이너가 잘 뜰까요? 그렇지 않습니다. 
nginx는 speedtest 이름을 찾을 수 없어서 
업스트림 호스트를 찾을 수 없다는 에러를 뿜습니다.

2022/06/18 03:16:21 [emerg] 1#1: host not found in upstream "speedtest:80" in /etc/nginx/conf.d/default.conf:7
2022/06/18 03:20:00 [emerg] 1#1: host not found in upstream "speedtest:80" in /etc/nginx/conf.d/default.conf:7
2022/06/18 03:34:04 [emerg] 1#1: host not found in upstream "speedtest:80" in /etc/nginx/conf.d/default.conf:7

docker-compose 파일을 수정하여 
별도의 bridge 네트워크를 만들어
두 컨테이너가 서로 통신하도록 해보겠습니다. 

docker bridge 네트워크 구성하기

docker는 다양한 네트워크를 구성을 제공합니다. 
그 중에서 우리의 요건에 맞는 것은 bridge 네트워크입니다. 
말그대로 다리처럼 컨테이너들이 소통할 수 있는 구조입니다. 

네, 그렇다고 합니다 (출처 : https://docs.docker.com/network/bridge/)

앞서 만들었던 docker-compose 파일에 
아래와 같이 network 설정을 추가했습니다. 

version: "2"
services:
  nginx:
    container_name: nginx-test
    image: nginx
    ports:
    - 443:443
    networks:
    - backbone
  speedtest:
    container_name: speedtest
    image: adolfintel/speedtest
    environment:
    - MODE=standalone
    networks:
    - backbone
    ports:
    - 80:80
networks:
  backbone:
    driver: bridge

이번엔 잘 될까요?
설레는 마음으로 sudo docker-compose up을 해봤습니다. 
그리고 브라우저에서 도메인에 접속해보니...

떴다!

 

네, 다행히 기대한 대로 잘 동작했습니다. 
nginx 설정에서도 업스트림 서버 이름으로 
컨테이너 이름을 사용할 수 있어서 편리합니다.
컨테이너간 통신, 어렵지 않네요!

728x90
728x90

파이썬을 사용하여 XML을 다룰때 BeautifulSoup을 많이 사용합니다.
새로 환경을 구성하여 BeautifulSoup을 이용하는데
이전에 보지 못했던 에러가 발생했습니다. 

강의 예제 코드 돌리다만난 에러라니...

 

핵심 에러 메세지는 다음과 같습니다.
BeautifulSoup 사용시 지정한 Feature가 없다는 내용입니다. 

FeatureNotFound: Couldn't find a tree builder with the features you requested: xml. Do you need to install a parser library?

 

lxml 패키지 설치하기

`xml`이 문제라고 하는데 정확히 어떤 라이브러리를 설치해야 하는지 알려주지는 않는군요.
구글을 통해 검색을 해보니 `lxml` 라이브러리의 설치가 필요한 것 같습니다. 
Jupyter 노트북을 사용중이라 아래와 같이 설치를 진행해 봤습니다.

!pip 로 주피터 노트북에서 직접 패키지를 설치해 봅니다

설치가 되었으니 이제 잘 되겠지...했으나...
계속 패키지가 없다고 에러가 나옵니다.
난감하네요.

하아... 계속 에러가...

 

그래서 조금 더 검색을 해보니
주피터 노트북을 재기동 하라는 이야기가 있습니다. 
구동중인 주피터를 중지하고 다시 실행했습니다.

Shutdown this notebook server (y/[n])? y
[C 11:01:20.436 NotebookApp] Shutdown confirmed
[I 11:01:20.439 NotebookApp] Shutting down 3 kernels
[I 11:01:20.443 NotebookApp] Kernel shutdown: 7a48be4a-c426-427b-b974-e8e26fccc994
[I 11:01:20.443 NotebookApp] Kernel shutdown: 45325d5b-9d8f-4f43-956f-d2b030475625
[I 11:01:20.443 NotebookApp] Kernel shutdown: d1b14c79-3741-4a14-9d0c-a5fe03a65532
[I 11:01:20.567 NotebookApp] Starting buffering for 45325d5b-9d8f-4f43-956f-d2b030475625:2d7ed833d3fe445c8b3ad49096ce9deb
[I 11:01:20.571 NotebookApp] Kernel shutdown: 45325d5b-9d8f-4f43-956f-d2b030475625
...
...
[I 11:01:20.967 NotebookApp] Shutting down 0 terminals
%
% jupyter notebook
[I 11:01:28.154 NotebookApp] Serving notebooks from local directory: /Users/nopd/dev
[I 11:01:28.154 NotebookApp] Jupyter Notebook 6.4.8 is running at:
[I 11:01:28.154 NotebookApp] http://localhost:8888/?token=731a38a75b038a956951174a7aa6da6d75acd13fe855ebd6
[I 11:01:28.154 NotebookApp]  or http://127.0.0.1:8888/?token=731a38a75b038a956951174a7aa6da6d75acd13fe855ebd6
[I 11:01:28.154 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 11:01:28.157 NotebookApp]

    To access the notebook, open this file in a browser:
        file:///Users/nopd/Library/Jupyter/runtime/nbserver-45577-open.html
    Or copy and paste one of these URLs:
        http://localhost:8888/?token=731a38a75b038a956951174a7aa6da6d75acd13fe855ebd6
     or http://127.0.0.1:8888/?token=731a38a75b038a956951174a7aa6da6d75acd13fe855ebd6

다시 파일을 열어 코드를 실행해보니 이제 잘 됩니다. 

주피터 재기동후 성공!

 

요약

0. 에러를 만난다
1. 에러를 잘 보고 필요한 패키지를 찾는다 : lxml
2. 주피터 노트북을 재기동한다
3. 계속 파이썬 코드를 잘 짠다

728x90

+ Recent posts