From 0a7040bff654ffd640c1d4c1fc10b0f7bd724f77 Mon Sep 17 00:00:00 2001 From: "kihwan.song" Date: Mon, 13 Jul 2026 10:59:36 +0900 Subject: [PATCH] =?UTF-8?q?vpn=20=EC=84=B8=ED=8C=85=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 8196 bytes connect-vpn/action.yml | 159 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 connect-vpn/action.yml diff --git a/.DS_Store b/.DS_Store index b9577faffbab9403f25422887352c46ea93a799f..9620eff58d3e0bb997d801aba05e8360ca530bd1 100644 GIT binary patch literal 8196 zcmeHMF>ezw6n;)qdQm9KP^3yMrXEFq)=D?u=ns$6nu67_O-%3T|ws#0dy z_yLHGor#4FiGc+PsT-{9`~mo$?b5rnNh1aXs$XP3pZz|&@3Y?X`AS5hvhS`E%@dJ@ z!n%-0b&l{jmot*lJvX2Q@Z_~tYmJ~Ap0P9?h5^HXVZbn87%&X{D-7VwX0b+``)btG zh5^ICrDTBfgN?$vto1-?nL1F(D*$vB-BQpla0A-bx~%m;X^cRGfUTbh$7D{X4SfMMV)1AKSS(h9YxLvi~4{^mz=tQ%CT zbuXx+&)RK$+g|+q@oswD9XlSj6W<21ML;P}4GPG|uZdPn%XB~?`S-n`p;tmMiv?J| z`YDA$Gz;4v5DpMcU|h`6#ZzY(NflVHB#?8kb%5yu!Rxk8R)mhwALEBvsFnT;=%)c(Fu|JKJN$gXRqmIWs;)G)$gqN(@pr<@UuCQ(v&2|z+GFt@9*?z8 z`u+9bcvI)T3oxhNPl`E*gB-FI=QhrcZJD9MAd6;{Bqu8g zZ=1{~vTc&+>W!%ZjEmVhI0Tu2>VZIj8%Vf + OTP를 비밀번호 필드에 넣는 방식. + append=정적PW+OTP 붙여쓰기 / replace=OTP만 / none=OTP미사용(정적PW만). + F5 로그온 페이지 설정에 맞게 지정. + + timeout: + required: false + default: "60" + description: 연결 완료 대기 최대 시간(초) + connected-pattern: + required: false + default: "session established|Connection established|已连接|connected" + description: > + f5fpc --info 출력에서 '연결됨'으로 판단할 정규식. + 클라이언트 버전/언어에 따라 다르니 `f5fpc --info` 실제 출력에 맞게 조정. + +runs: + using: composite + steps: + - name: 의존성/클라이언트 설치 + shell: bash + env: + ACTION_PATH: ${{ github.action_path }} + DEB_PATH: ${{ inputs.deb-path }} + DEB_URL: ${{ inputs.deb-url }} + run: | + set -eu + + # root가 아니면 sudo 사용 + SUDO="" + [ "$(id -u)" -ne 0 ] && SUDO="sudo" + + # oathtool(TOTP 생성) 설치 확인 + if ! command -v oathtool >/dev/null 2>&1; then + if command -v apt-get >/dev/null 2>&1; then + $SUDO apt-get update && $SUDO apt-get install -y oathtool + else + echo "oathtool 설치 실패: apt 기반 러너가 아님" + exit 1 + fi + fi + + # 설치할 .deb 결정: deb-path > deb-url > 액션 폴더의 *.deb + DEB="" + if [ -n "$DEB_PATH" ]; then + DEB="$DEB_PATH" + elif [ -n "$DEB_URL" ]; then + DEB="/tmp/f5-client.deb" + curl -fsSL -o "$DEB" "$DEB_URL" + else + DEB=$(ls "$ACTION_PATH"/*.deb 2>/dev/null | head -1 || true) + fi + + if [ -z "$DEB" ] || [ ! -f "$DEB" ]; then + echo ".deb를 찾을 수 없습니다 (deb-path/deb-url/액션폴더 확인)" + exit 1 + fi + + echo "F5 클라이언트 설치: $DEB" + # dpkg 후 의존성 깨지면 apt-get install -f로 보정 + $SUDO dpkg -i "$DEB" || $SUDO apt-get install -f -y + + # f5fpc 존재 확인 + if ! command -v f5fpc >/dev/null 2>&1; then + echo "f5fpc가 설치되지 않았습니다 (.deb 내용/PATH 확인)" + exit 1 + fi + + - name: TUN 디바이스 확인 + shell: bash + run: | + set -eu + # VPN 인터페이스 생성에는 /dev/net/tun + NET_ADMIN이 필요합니다. + # 러너 컨테이너 옵션: --cap-add=NET_ADMIN --device /dev/net/tun + if [ ! -c /dev/net/tun ]; then + echo "/dev/net/tun 이 없습니다. 러너에 --device /dev/net/tun --cap-add=NET_ADMIN 필요" + exit 1 + fi + + - name: VPN 연결 + shell: bash + env: + VPN_HOST: ${{ inputs.vpn-host }} + VPN_USER: ${{ inputs.vpn-user }} + VPN_PASS: ${{ inputs.vpn-password }} + OTP_SEED: ${{ inputs.otp-seed }} + OTP_MODE: ${{ inputs.otp-mode }} + TIMEOUT: ${{ inputs.timeout }} + CONNECTED_PATTERN: ${{ inputs.connected-pattern }} + run: | + set -eu + + SUDO="" + [ "$(id -u)" -ne 0 ] && SUDO="sudo" + + # TOTP 코드 로컬 생성 (API 불필요) + OTP=$(oathtool --totp -b "$OTP_SEED") + + # OTP 결합 방식에 따라 password 필드 구성 + case "$OTP_MODE" in + append) PASSFIELD="${VPN_PASS}${OTP}" ;; + replace) PASSFIELD="${OTP}" ;; + none) PASSFIELD="${VPN_PASS}" ;; + *) echo "잘못된 otp-mode: $OTP_MODE (append|replace|none)"; exit 1 ;; + esac + + echo "VPN 연결 시도: ${VPN_HOST} (user=${VPN_USER}, otp-mode=${OTP_MODE})" + # 참고: f5fpc 플래그는 클라이언트 버전마다 다를 수 있음 (`f5fpc --help`로 확인). + # 비대화식 실행을 위해 --nogui/--nocheck 사용. + $SUDO f5fpc --start \ + --host "$VPN_HOST" \ + --user "$VPN_USER" \ + --password "$PASSFIELD" \ + --nocheck --nogui || true + + # 연결은 백그라운드 데몬에서 비동기로 진행 → --info를 폴링해 완료 대기 + echo "연결 완료 대기 중 (최대 ${TIMEOUT}초)..." + for i in $(seq 1 "$TIMEOUT"); do + INFO=$($SUDO f5fpc --info 2>/dev/null || true) + if echo "$INFO" | grep -Eqi "$CONNECTED_PATTERN"; then + echo "VPN 연결 완료" + echo "$INFO" + exit 0 + fi + sleep 1 + done + + echo "VPN 연결 실패 (${TIMEOUT}초 초과). 마지막 상태:" + $SUDO f5fpc --info 2>/dev/null || true + exit 1