LabHub
开始
学习 学习路径 课程

隔离网络镜像与私有 CA

在隔离网络中搭建内部 DNS 与时间服务器

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

이 실습은 진짜 VM 에서 돕니다

우분투 24.04 VM 한 대입니다. 준비 단계가 네트워크 네임스페이스 client 를 만들어 두었습니다 — 같은 VM 안이지만 네트워크로는 따로인 "폐쇄망 안의 다른 서버" 이고, VM(10.203.0.1)과 veth 로 이어져 있습니다(10.203.0.2). 그 안에서 명령을 치려면 ip netns exec client <명령> 입니다. dnsmasq·chrony·dig 가 깔려 있습니다(dnsmasq 서비스는 포트 53 충돌로 실패한 채입니다 — 그 진단은 network-basics 코스에서 다룹니다). 채점은 바깥에서 VM 의 8899 포트로 들어오는 에이전트가 하므로 이미 맺은 연결을 막으면 채점이 끊깁니다.

목표

인터넷에 닿지 않는 망에 사내 DNS 와 시간 서버를 세우고, 다른 서버가 그것을 쓰게 한 뒤, 인계용 점검 스크립트로 끝낸다.

왜 중요한가

사내 미러는 이름으로 불러야 인증서와 맞고, 그 이름을 푸는 DNS 가 있어야 한다. 그런데 폐쇄망 DNS 가 모르는 이름을 바깥에 물으러 가면 매번 시간 초과를 기다린다. 사내 영역은 권한을 가지고 곧바로 답하게 만들어야 한다. 시간도 같다. 인터넷 시간 서버에 닿지 않는 서버들의 시계는 서로 멀어지고, 몇 분만 어긋나도 인증서 유효 기간 확인과 로그 대조가 깨진다. 폐쇄망에는 기준 시계 하나가 있어야 한다.

예상 50분이다. 세션이 끝나면 VM 이 사라지니 남기고 싶은 파일은 종료 전에 따로 보관한다.

단계

  1. 다시 돌려도 규칙이 한 벌만 남는 /root/infra/egress.sh 로 바깥 송신을 막는다(체인 AIRGAP-EGRESS, OUTPUT 에서 한 번). 루프백·이미 맺은 연결·사내 대역 10.203.0.0/24 는 살린다. 막기 전과 막은 뒤에 curl -s -o /dev/null -w '%{http_code}' https://ubuntu.com 을 재서 /root/infra/egress-proof.txtbefore=·after= 로 적는다.
  2. /etc/dnsmasq.d/airgap.conf 로 dnsmasq 가 10.203.0.1 에서만 듣고, 상류 없이, airgap.internal 영역을 권한으로 답하게 한다. 이름표는 /etc/airgap/hosts(registry·pypi·ntp 세 이름 → 10.203.0.1)에 두고 addn-hosts 로 읽는다. 서비스를 살리고 부팅 때도 뜨게 한다.
  3. client 가 그 DNS 와 검색 도메인 airgap.internal 을 쓰게 /etc/netns/client/resolv.conf 를 쓴다. client 에서 짧은 이름 registry 가 풀려야 한다.
  4. /etc/airgap/hostsnexus.airgap.internal10.203.0.1 을 더하고 dnsmasq 를 재시작하지 않고 반영한다. 반영 전후의 dnsmasq 주 프로세스 PID 를 /root/infra/reload.txtpid_before=·pid_after= 로 적는다.
  5. /etc/chrony/conf.d/airgap-server.conf 로 chrony 가 사내 대역에 시간을 내주고, 상류가 없어도 층위 8 로 기준이 되게 한다.
  6. client 에서 시계를 바꾸지 않고 10.203.0.1 에 시간을 물어 그 출력을 /root/infra/ntp-query.txt 에 저장한다.
  7. 인계용 점검 스크립트 /root/infra/check.sh <네임스페이스> 를 쓴다. 그 네임스페이스에서 registry·pypi·ntp 가 풀리고 시간 서버가 답하면 0, 아니면 0 이 아닌 값으로 끝난다.

참고

바깥 송신을 막아 폐쇄망 만들기

/root/infra/egress.sh 로 바깥 송신을 막고(체인 AIRGAP-EGRESS), 막기 전후의 https://ubuntu.com 상태 코드를 /root/infra/egress-proof.txtbefore=·after= 로 적는다.

새 체인을 만들어 OUTPUT 맨 앞에서 그리로 보내면, 비우고 다시 채우는 방식으로 몇 번을 돌려도 같은 모양이 됩니다. 살릴 것(루프백, 이미 맺은 연결, 채점 에이전트, 사내 대역)을 먼저 RETURN 으로 적고 마지막에 막습니다.

상류 없는 사내 DNS

/etc/dnsmasq.d/airgap.conf 로 dnsmasq 가 10.203.0.1 에서만 듣고 상류 없이 airgap.internal 을 권한으로 답하게 하고, 이름표는 /etc/airgap/hosts 에 두어 읽게 한다. 서비스를 살리고 부팅 때도 뜨게 한다.

듣는 주소를 하나로 좁히는 두 줄, 상류를 끊는 한 줄, 영역을 로컬로 선언하는 한 줄, 이름표 파일을 읽는 한 줄이 필요합니다. 없는 사내 이름이 곧바로 '없음' 으로 답해지는지 dig 의 status 로 확인하세요.

다른 서버가 사내 DNS 를 쓰게

client10.203.0.1 과 검색 도메인 airgap.internal 을 쓰게 /etc/netns/client/resolv.conf 를 쓴다.

ip netns exec 는 /etc/netns/<이름>/resolv.conf 가 있으면 그 네임스페이스 안에서 /etc/resolv.conf 자리에 끼워 줍니다. nameserver 와 search 두 줄이면 됩니다. 확인은 client 안에서 짧은 이름으로 dig +search.

재시작 없이 이름 더하기

/etc/airgap/hostsnexus.airgap.internal10.203.0.1 을 더하고 dnsmasq 를 재시작하지 않고 반영한다. 반영 전후의 주 프로세스 PID 를 /root/infra/reload.txtpid_before=·pid_after= 로 적는다.

dnsmasq 는 SIGHUP 을 받으면 캐시를 비우고 /etc/hosts 와 addn-hosts 파일을 다시 읽습니다(설정 파일 자체는 다시 읽지 않습니다). systemd 의 reload 가 무엇을 보내는지도 확인해 보세요.

상류 없는 사내 시간 서버

/etc/chrony/conf.d/airgap-server.conf 로 chrony 가 10.203.0.0/24 에 시간을 내주고, 상류가 없어도 층위 8 로 기준이 되게 한다.

chrony 는 기본으로 아무 클라이언트도 받지 않습니다. 받을 대역을 허락하는 지시자와, 상류 없이 자기 시계를 기준으로 내주는 지시자가 필요합니다. 우분투의 chrony.conf 는 conf.d 를 읽습니다. 바꾼 뒤 서비스를 다시 띄우고 tracking 의 Stratum 을 보세요.

다른 서버에서 시간 묻기

client 에서 시계를 바꾸지 않고 10.203.0.1 에 시간을 물어 출력을 /root/infra/ntp-query.txt 에 저장한다.

chronyd 에는 설정 파일 대신 명령줄 지시자로 한 번 묻고, 시계는 바꾸지 않고 차이만 찍고 끝나는 모드가 있습니다. 네임스페이스 안에서 돌리고, 몇 초 기다리도록 제한 시간을 주세요.

인계용 점검 스크립트

/root/infra/check.sh <네임스페이스> 를 쓴다. 그 네임스페이스에서 registry·pypi·ntp 가 풀리고 시간 서버가 답하면 0, 아니면 0 이 아닌 값으로 끝난다.

채점기는 이 스크립트를 client 와, 사내망에 이어지지 않은 빈 네임스페이스 두 곳에 돌립니다. 앞의 것은 0, 뒤의 것은 0 이 아니어야 합니다. dig 와 chronyd -Q 에 짧은 제한 시간을 주세요.