Alpine Linux 기반으로 호스트 수정 없이 IP 2개를 할당하여 각각의 VM을 켜고 RDP를 연결하며 10분 미사용 시 종료하는 전체 세팅 과정.
1. PVE API 토큰 발급 (사전 준비)
-
Proxmox 웹 GUI 접속 → Datacenter → Permissions → API Tokens 메뉴로 이동.
-
Add 버튼 클릭 → User는
root@pam선택, Token ID는rdp입력. -
생성 버튼을 누르면 나오는 Secret Key를 반드시 복사.
- _토큰 형태 예시: `PVEAPIToken=root@pam!rdp=여기에시크릿키
2. Alpine LXC 생성 및 네트워크 설정 (IP 2개 할당 필요시)
-
Proxmox GUI에서 Create CT를 눌러 Alpine 템플릿으로 컨테이너를 생성
-
Network 탭에서 첫 번째 IP(예:
192.168.1.21/24)와 Gateway를 입력하고 생성 -
LXC 콘솔에 접속하여 두 번째 IP를 추가
vi /etc/network/interfaces -
파일 맨 아래에 두 번째 IP(예:
.22) 설정을 추가auto eth0:1 iface eth0:1 inet static address 192.168.1.22/24 -
네트워크 재시작
rc-service networking restart
3. 필수 패키지 설치
apk update
apk add socat net-tools curl4. 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.sh5. 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 start6. 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.shCron 등록
crontab -e1분마다 실행
* * * * * /usr/local/bin/auto-stop.sh 210 10.1.0.11
Cron 서비스 실행 및 활성화
rc-update add crond default
rc-service crond start7. Remmina 접속
-
Remmina에서 새 RDP 프로필을 생성
-
서버 주소에 **LXC에 할당한 IP (예: 192.168.1.21)**를 입력
-
고급(Advanced) 탭에서 **접속 제한 시간(Connect timeout)**을 60초로 설정
-
접속을 누르면 화면이 멈춘 상태로 VM이 부팅될 때까지 대기하다가, 부팅 완료 시 바로 윈도우 화면이 나옴