Alpine Linux 기반으로 호스트 수정 없이 IP 2개를 할당하여 각각의 VM을 켜고 RDP를 연결하며 10분 미사용 시 종료하는 전체 세팅 과정.

1. PVE API 토큰 발급 (사전 준비)

  1. Proxmox 웹 GUI 접속 Datacenter Permissions API Tokens 메뉴로 이동.

  2. Add 버튼 클릭 User는 root@pam 선택, Token ID는 rdp 입력.

  3. 생성 버튼을 누르면 나오는 Secret Key를 반드시 복사.

    • _토큰 형태 예시: `PVEAPIToken=root@pam!rdp=여기에시크릿키

2. Alpine LXC 생성 및 네트워크 설정 (IP 2개 할당 필요시)

  1. Proxmox GUI에서 Create CT를 눌러 Alpine 템플릿으로 컨테이너를 생성

  2. Network 탭에서 첫 번째 IP(예: 192.168.1.21/24)와 Gateway를 입력하고 생성

  3. LXC 콘솔에 접속하여 두 번째 IP를 추가

    vi /etc/network/interfaces
  4. 파일 맨 아래에 두 번째 IP(예: .22) 설정을 추가

    auto eth0:1
    iface eth0:1 inet static
        address 192.168.1.22/24
    
  5. 네트워크 재시작

    rc-service networking restart

3. 필수 패키지 설치

apk update
apk add socat net-tools curl

4. RDP 게이트웨이 스크립트 작성

/usr/local/bin/rdp-gateway.sh 파일을 생성

vi /usr/local/bin/rdp-gateway.sh

아래 내용을 붙여넣고 환경에 맞게 PVE_IP, PVE_NODE, TOKEN을 수정

#!/bin/bash
 
VM_ID=$1
TARGET_IP=$2
 
PVE_IP="192.168.0.1"
PVE_NODE="pve"
TOKEN="PVEAPIToken=root@pam!apiname=여기에발급받은시크릿키"
 
# [핵심] 스크립트에서 발생하는 모든 에러를 로그 파일로 버림.
# 이게 없으면 텍스트가 RDP 클라이언트로 넘어가서 연결이 튕김.
exec 2> /tmp/rdp-gateway-error.log
 
# 1. VM 현재 상태 확인
STATUS=$(curl -s -k -H "Authorization: $TOKEN" "https://$PVE_IP:8006/api2/json/nodes/$PVE_NODE/qemu/$VM_ID/status/current" | jq -r '.data.status')
 
# 2. VM이 켜져있지 않을 때만 부팅 요청
if [ "$STATUS" != "running" ]; then
	curl -s -k -X POST "https://$PVE_IP:8006/api2/json/nodes/$PVE_NODE/qemu/$VM_ID/status/start" -H "Authorization: $TOKEN" > /dev/null
fi
 
# 3. VM의 3389 포트 응답 대기
for i in {1..60}; do
    # nc가 성공하면 루프 탈출
    nc -z -w 1 $TARGET_IP 3389 > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        break
    fi
    sleep 1
done
 
touch "/tmp/vm_active_$VM_ID"
 
# 3. 트래픽 중계
exec nc $TARGET_IP 3389

실행 권한 부여

chmod +x /usr/local/bin/rdp-gateway.sh

5. OpenRC 서비스 등록 (부팅 시 상시 대기)

Service 1 (VM1 용)

vi /etc/init.d/rdp-vm1
#!/sbin/openrc-run
 
name="RDP Gateway VM1"
 
# 3389 포트로 접속이 오면, rdp-gateway.sh에 파라미터를 주고 실행시킴
command="/usr/bin/socat"
command_args="TCP4-LISTEN:3389,bind=192.168.0.11,reuseaddr,fork EXEC:\"/usr/local/bin/rdp-gateway.sh 210 10.1.0.11\""
command_background=true
pidfile="/run/rdp-vm1.pid"

권한 부여 및 부팅 시 자동 실행 등록

chmod +x /etc/init.d/rdp-vm1
rc-update add rdp-vm1 default
rc-service rdp-vm1 start

6. 10분 미사용 자동 종료 스크립트 (Cron 활용)

vi /usr/local/bin/auto-stop.sh
#!/bin/bash
 
VM_ID=$1
TARGET_IP=$2
 
PVE_IP="192.168.1.2"
PVE_NODE="pve"
TOKEN="PVEAPIToken=root@pam!rdp=여기에발급받은시크릿키"
 
ACTIVE_FLAG="/tmp/vm_active_$VM_ID"
STATE_FILE="/tmp/rdp_idle_$VM_ID"
 
# 1. 플래그 파일이 없으면 실행 안 함 (이미 꺼져 있거나 수동 종료됨)
if [ ! -f "$ACTIVE_FLAG" ]; then
    exit 0
fi
 
# 2. 세션 확인
CONN=$(netstat -tn | grep "$TARGET_IP" | grep "3389" | grep -c "ESTABLISHED")
 
if [ "$CONN" -eq 0 ]; then
    # 연결이 없으면 카운트 1 증가
    COUNT=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
    COUNT=$((COUNT + 1))
    echo "$COUNT" > "$STATE_FILE"
    
    # 10분(10회) 도달 시 종료 후 카운트 초기화
    if [ "$COUNT" -ge 10 ]; then
        STATUS=$(curl -s -k -H "Authorization: $TOKEN" "https://$PVE_IP:8006/api2/json/nodes/$PVE_NODE/qemu/$VM_ID/status/current" | jq -r '.data.status')
        
        if [ "$STATUS" == "running" ]; then
            # 1. 먼저 정상 종료(shutdown) 시도
            curl -s -k -X POST "https://$PVE_IP:8006/api2/json/nodes/$PVE_NODE/qemu/$VM_ID/status/shutdown" -H "Authorization: $TOKEN" > /dev/null
            
            # 2. 60초간 대기하며 10초마다 꺼졌는지 확인
            for i in {1..6}; do
                sleep 10
                CHECK=$(curl -s -k -H "Authorization: $TOKEN" "https://$PVE_IP:8006/api2/json/nodes/$PVE_NODE/qemu/$VM_ID/status/current" | jq -r '.data.status')
                if [ "$CHECK" == "stopped" ]; then
                    break
                fi
            done
            
            # 3. 60초가 지났는데도 여전히 켜져 있다면 강제 종료(stop)
            if [ "$CHECK" == "running" ]; then
                curl -s -k -X POST "https://$PVE_IP:8006/api2/json/nodes/$PVE_NODE/qemu/$VM_ID/status/stop" -H "Authorization: $TOKEN" > /dev/null
            fi
        fi
        
        rm -f "$STATE_FILE"
        rm -f "$ACTIVE_FLAG"
    fi
else
    # 연결이 있으면 카운트 초기화
    echo 0 > "$STATE_FILE"
fi

권한 부여

chmod +x /usr/local/bin/auto-stop.sh

Cron 등록

crontab -e

1분마다 실행

* * * * * /usr/local/bin/auto-stop.sh 210 10.1.0.11

Cron 서비스 실행 및 활성화

rc-update add crond default
rc-service crond start

7. Remmina 접속

  1. Remmina에서 새 RDP 프로필을 생성

  2. 서버 주소에 **LXC에 할당한 IP (예: 192.168.1.21)**를 입력

  3. 고급(Advanced) 탭에서 **접속 제한 시간(Connect timeout)**을 60초로 설정

  4. 접속을 누르면 화면이 멈춘 상태로 VM이 부팅될 때까지 대기하다가, 부팅 완료 시 바로 윈도우 화면이 나옴