카테고리: Layer7

Microsoft PowerShell을 이용한 DNS 서버 레코드 갱신

 

네트워크 관련 작업을 하다 보면 (주로 비용상의 문제로) 유동 IP를 사용해야 하는 경우가 생기곤 한다.
유동 IP 환경에서 서비스를 제공하기 위하여 주로 DDNS를 사용하게 되는데, 웬만한 도메인 서비스들은 DDNS 서비스를 자체적으로 제공하지만, 만약 자체 도메인 서버를 운용하는 경우라면 어떨까?

리눅스라면 BIND와 쉘 스크립트라는 걸출한 물건이 존재한다. 그리고 윈도우에서는 PowerShell을 이용하여 DNS 서버를 관리할 수 있다.

 

PowerShell로 서버를 관리하기 위해서는 몇 가지 전제 조건이 필요하다.

1. WinRM 서비스가 활성화되어 있어야 한다.
2. PSRemoting이 활성화되어 있어야 한다.
3. WinRM 서비스에서 클라이언트/서버가 각각 신뢰하는 호스트로 등록되어 있어야 한다.
4. WinRM 서비스 포트인 TCP 5985/5986이 열려있어야 한다.
5. 클라이언트에서 파워 쉘 스크립트 실행 권한(Set-ExecutionPolicy)이 주어져 있어야 한다.

 

먼저 서버에서 PSRemoting을 활성화해야 한다. 파워 쉘을 관리자 권한으로 열고, 다음 명령을 입력한다.

기본적으로 PSRemoting은 같은 홈/도메인 네트워크 안, 동일한 서브넷 내에서만 허용되어 있다.
이 제약을 풀기 위하여 다음과 같은 명령어를 입력한다.

이제 서버와 클라이언트에서 서로를 신뢰하는 호스트로 지정해주어야 한다.

호스트 이름은 IP 혹은 FQDN이 될 수 있으며, ‘,'(콤마)로 구분된다. 만약 모든 호스트에 대하여 허용하고 싶다면 *(와일드카드 문자열)을 사용하자.

 

이 시점에서 WinRM 서비스가 시작되어 있지 않다면 등록 과정에서 에러가 발생한다. 경고 메시지에서는 자동으로 WinRM 서비스를 시작한다고 하지만, 실제로는 실행되지 않는다.
그러므로 수동으로 시작해준다.

WinRm 서비스가 시작된 후 정상적으로 신뢰하는 호스트 등록이 가능할 것이다.

 

이렇게 서버-클라이언트의 설정이 마무리되면, 접속을 테스트 해 본다.

접속이 정상적으로 이루어진다면 이러한 메시지가 나올 것이다. 만약 접속되지 않는다면 방화벽과 신뢰하는 호스트의 설정을 다시 살펴보자.

접속에 성공하였다면 원격 세션을 통하여 PowerShell을 실행할 준비가 되었다는 뜻이다.

 

이제 실제로 원격 세션을 열어보자. PowerShell에서 원격 세션을 얻을 수 있는 명령어는 크게 두 가지가 있다.

둘 다 원격 세션을 생성하지만, Enter-PSSession은 프롬프트에 직접 로그인하고, New-PSSession은 세션 객체를 만든다는 차이가 있다.

단순히 명령어를 실행하는 것은 Enter-PSSession이 더 간단하지만, 명령을 수행한 결과를 Return한다거나, 로컬 변수를 이용하여 명령을 수행해야 하는 경우에는 New-PSSession이 더 적합하다.

 

New-PSSession을 이용하여 원격 세션을 만드는 것은 아주 간단하다.

여기서 Credential 옵션은 인증 정보를 제공한다. 공란으로 두거나 String을 입력하였을 경우, 윈도 로그인 창이 팝업되고 인증 정보를 입력할 수 있다.
하지만 우리의 목적은 스크립트를 이용한 자동화이므로 수동으로 자격 증명을 입력하는 것은 바람직하지 않다. 그렇다면 어떻게 인증 정보 입력을 자동화 할 수 있을까?

 

정답은 Credential 옵션에 PSCredential 오브젝트를 넘겨주는 것이다. 단, 이 때 주의할 것은 PowerShell Credential에서 패스워드는 암호화 된 스트링으로 지정된다는 점이다.
Plain String을 넣을 경우 인증이 이루어지지 않는다. 그러므로 먼저 Plain-Text를 SecureString으로 변환해주어야 한다.

새로운 secureString 객체를 만들고 password를 SecureString으로 변환하였다.

 

그리고 PSCredential 오브젝트를 만들 때 아이디와 SecureString을 인자로 넘겨주고, PSCredential로 인증을 수행한다.
이것으로 새로운 PSSession 객체를 얻었다.

 

원격 접속이 성립하였으니, 원격으로 명령어를 실행해야 할 것이다. 원격 명령어 실행을 위해 사용하는 것이 바로 Invoke-Command 명령어다.

Invoke-Command 명령어의 문법은 다음과 같다.

여기서 지역 변수를 전달하고 싶다면 params()와 -ArgumentList 옵션을 사용한다.

 

이 명령어를 이용해 가장 먼저 할 일은 DNSServer 모듈이 존재하는지 확인하는 것이다.

DNSServer Cmdlet이 존재한다면 모듈 목록에 DnsServer가 나올 것이다.

 

DNSServer Cmdlet이 있다면 실제로 DNS 서버의 레코드를 읽고, 변경할 수 있다.
지금은 DDNS를 적용할 것이므로, 레코드의 값을 변경하는 명령어인 Set-DnsServerResourceRecord를 이용해야 한다.

Set-DnsServerResourceRecord cmdlet은 목표 레코드를 리소스 레코드 오브젝트를 통하여 검색한다. 즉, 그 오브젝트와 일치하는 대상을 수정할 수 있다.
그러므로 우리는 먼저 Get-DnsServerResourceRecord를 통하여 목표 리소스 레코드 오브젝트를 얻고, 그것을 수정하여 새로운 변수에 담고, 원본 리소스 레코드를 트리거로 삼아 목표 값을 갱신할 수 있다.

이 때, IPv4 Address의 경우 String을 직접 입력하지 못하므로, System.Net.IPAddress 객체로 변환해주어야 한다는 점에 유의하자.

 

백문이 불여일견, 샘플 소스를 하나 올려두겠다.

 

마지막 줄의 Get-PSSession | Remove-PSSession을 통해 사용이 끝난 세션은 반드시 종료하자.

CCNA Study – DHCP

 

DHCP (Dynamic Host Configuration Protocol)는 호스트의 네트워크 설정을 쉽게 하기 위하여 개발된 프로토콜이다.

이에 앞서 RARP라는 자동 IPv4 할당 프로토콜이 있었지만, RARP는 오로지 IP만을 정적(Static)으로 할당받을 수 있었기에 디폴트 게이트웨이, 서브넷 마스크, DNS 서버 주소 등의 통신에 필요한 추가적인 정보를 제공받을 수 있는 새로운 방법이 필요했고, IETF는 RFC 951에서 BOOTP를 정의하여 이 문제를 해결하였다.

그러나 BOOTP는 여전히 IP를 Static하게만 할당할 수 있었고, 유연성 부족과 확장 옵션의 비표준화 등의 문제로 인해 BOOTP를 개량한 DHCP가 RFC 2131에서 새로 정의되었다.

 

그럼, 일반적인 환경에서의 DHCP 동작 알고리즘을 살펴보자.

 

1. 클라이언트는 부팅이 완료된 뒤 UDP 68번 포트로 DHCP DISCOVER 메시지를 보낸다.

2. DHCP 서버는 DISCOVER 메시지를 수신한 뒤 해당 클라이언트에게 DHCP OFFER 메시지를 전송, 자신이 IP를 제공할 수 있음을 알린다.

3. DHCP 클라이언트는 자신이 수신한 OFFER 중 하나를 선택(DHCP 서버가 다수일 경우), DHCP REQUEST 메시지를 브로드캐스팅한다. 이는 자신이 선택한 IP 주소를 알리고, 선택받지 못한 다른 서버들이 IP 주소를 재사용할 수 있게 하기 위함이다.

4. DHCP 서버가 DHCP 클라이언트에게 DHCP ACK 메시지를 전송함으로써 IP 할당이 완료된다.

5. 클라이언트는 자신이 할당받은 IP로 ARP Probe를 전송함으로써 충돌 확인을 한다. 만약 ARP Reply가 돌아오지 않으면 이 IP를 사용하게 된다.

 

앞서 말했듯이 DHCP는 이전에 사용하던 RARP/BOOTP의 부족한 부분을 보완하여 만들어졌다. 또한 여러 상황들에 유연하게 대응할 수 있도록 확장성 있는 구조를 가지는데, 상세 동작을 다루기 위해서는 먼저 DHCP 패킷의 구조를 이해할 필요가 있다.

 

DHCP 패킷은 다음과 같이 구성되어 있다.

 

1. Opcode (1Byte): DHCP 메시지의 타입을 나타낸다. 1은 BOOTREQUEST(요청), 2는 BOOTREPLY(응답)라 한다.

2. Hardware Type (1Byte): L2 Protocol의 유형을 나타낸다. ARP의 그것과 동일하다.

3. Hardware Length (1Byte): 하드웨어 주소 길이를 바이트 단위로 나타낸다.

4. Hop Count (1Byte): DHCP Relay가 사용될 경우 패킷이 중계된 횟수를 나타낸다. 기본값은 0이며, 경유한 Relay Agent마다 1씩 증가한다.

5. Transaction ID (4Byte): 클라이언트가 선택하는 랜덤한 32비트짜리 수이다. DISCOVER와 OFFER를 짝짓는데 사용한다.

6. Number of Seconds (2Byte): 임대 획득/갱신 이후 경과한 시간을 나타낸다.

7. Broadcast Flags (2Byte): 첫번째 비트가 0이면 응답 메시지를 유니캐스트로, 1이면 브로드캐스트로 전송한다.

8. Client IP Address (4Byte): 클라이언트의 IP 주소를 나타낸다. 최초 요청시에는 IP가 할당되지 않았으므로 0.0.0.0이 들어간다.

9. Your IP Address (4Byte): 클라이언트에게 할당되는 IP 주소로, 서버의 응답 메시지에 포함된다.

10. Client H/W Address (16Byte): 할당을 요청한 클라이언트의 하드웨어 주소가 들어간다.

11. Server Name String (64Byte): 서버 호스트 이름. 널 문자로 끝난다.

12. Options (가변 길이): DHCP 옵션들을 나타낸다. 최초 4바이트가 0x63, 0x82, 0x53, 0x63으로 되어 있다. 이 ‘Magic Cookie’는 RFC 1497 (BOOTP Extension)에서 정의된 것으로, BOOTP와의 호환성을 유지하기 위해 사용된다.

 

이를 그림으로 나타내면 다음과 같다.

 

All Rights Reserved ktworld.co.kr
All Rights Reserved ktworld.co.kr

 

BOOTP 프로토콜과 비교해 보면, 마지막 Option Field만이 약간 달라진 것을 알 수 있다.

DHCP Option Field의 구조는 다음과 같으며, DHCP는 이 Option Field를 이용하여 BOOTP와는 다른 확장 기능들을 구현한다.

All Rights Reserved ktworld.co.kr
All Rights Reserved ktworld.co.kr

 

그러면 이제 DHCP Option들에 대해 알아보자.

실제 사용할 수 있는 DHCP Option은 굉장히 많으나, 이 중 RFC 2132에서 정의된 것은 다음과 같다.

DHCP Option
All Rights Reserved IANA

 

전체 옵션 리스트는 다음 파일을 참조하라.

 options.xlsx

 

이 글에서는 IP  할당 및 임대 갱신에 사용되는 Option 50, 51, 53, 54, 61과 네트워크 통신을 위한 추가 정보를 제공하는 Option 1, 3, 5, 6, 15에 대해 서술한다.

 

Option 1 (Subnet Mask): 해당 클라이언트의 Subnet Mask를 지정한다.

Option 3 (Router): 해당 클라이언트의 Default Gateway를 지정한다.

Option 5 (Name Server): 클라이언트가 사용할, IEN 116에 정의된 네임서버의 주소를 지정한다.

Option 6 (Domain Server): 클라이언트가 사용할 DNS 주소를 지정한다.

Option 15 (Domain Name): 클라이언트의 도메인 이름을 지정한다.

Option 50 (Address Request): DHCP 서버가 클라이언트에게 할당할 IP Address를 지정한다.

Option 51 (Address Time): 할당해줄 IP Address의 임대 만료 시간을 지정한다.

Option 53 (DHCP Msg Type): DHCP 메시지의 타입을 지정한다. 아래의 표를 참조하라.

dhcp_msg

Option 54 (DHCP Server ID): DHCP 메시지를 전송한 서버의 IP 주소를 알린다.

Option 61 (DHCP Client ID): 클라이언트를 식별할 수 있는 식별자가 들어간다. 이 식별자로는 클라이언트의 MAC Address, FQDN 등이 사용될 수 있다.

 

부록

A. DHCP Relay Agent

DHCP의 설정 과정에서 브로드캐스팅이 사용되기 때문에 DHCP의 동작 범위는 기본적으로 하나의 서브넷으로 한정된다. 그러나 대규모 네트워크에서 이러한 구성은 다수의 DHCP 서버를 필요로 하고, 높은 비용을 발생시키며, 관리를 어렵게 만든다.

이에 따라 제안된 것이 바로 DHCP Relay Agent이다.

DHCP Relay Agent는 DHCP 서버와 클라이언트 간의 메시지 전달을 중계하여 DHCP 메시지가 서브넷을 넘어서 이동할 수 있도록 한다.

 

다음으로 DHCP Relay Agent가 어떻게 동작하는지 알아보자.

1. 클라이언트가 DHCP Discover 메시지를 브로드캐스팅한다.

2. Relay Agent는 Discover 메시지를 수신, DHCP 서버로 유니캐스팅한다. 이 때 Giaddr(Gateway Address)에 0.0.0.0 대신 자신의 IP를 기록하여 이 메시지가 Relay Agent로부터 온 것임을 서버에게 알린다.

3. DHCP 서버는 Giaddr 필드의 주소에 맞는 IP 풀을 선택, IP를 할당하고 Relay Agent의 주소로 DHCP Offer 메시지를 보낸다.

4. Relay Agent는 DHCP Offer를 클라이언트에게 중계한다. 이 때 Discover 메시지 안의 Broadcast Flag가 0이면 유니캐스트로, 1이면 브로드캐스트로 전송한다.

 

이것으로 Relay Agent의 기본적인 동작을 알아보았다.

그런데 메시지가 Relay Agent를 지날 때 Giaddr 필드에 Relay 자신의 IP를 기록한다면, 다수의 Relay를 거쳐서 서버로 요청이 전송되는 경우에는 서버가 클라이언트의 IP 대역을 잃어버리게 된다(Giaddr 주소에 근거하여 판단하므로) 따라서 여러 릴레이를 거치는 구성은 불가능한데, 어째서 Hop Count가 존재할까?

나는 이것이 DHCP 패킷이 루핑 등의 이유로 네트워크를 계속 떠돌아다니는 것을 막기 위해서 사용된다고 결론지었다. 실제로 여러 네트워크 회사의 DHCP 서버 설정에 max-hop-count가 존재하기도 하고.

만약 다른 이유가 있거나, 다수의 릴레이를 거치는 구성이 가능하다면 의견을 남겨 주길 바란다.

 

B. APIPA

DHCP 클라이언트가 DHCP를 통한 IP 할당에 실패하는 경우, 클라이언트는 네트워크와의 연결을 위해 APIPA(Automatic Private IP Addressing)을 사용해 169.254.0.0/16의 주소 중 하나를 임의로 할당한다.

APIPA는 RFC3927에서 정의되었고, BOOTP와 마찬가지로 네트워크 구성에 필요한 여러 정보를 얻을 수 없기 때문에 소규모 사설 네트워크에서의 통신에서만 사용될 수 있다.