2026-08-27 세션 — 미니PC 원부자재발주서 「거래처 DB 연결」 미갱신 · rdstunnel
지시
페페: 「다를 발주서로 테스트도 좋다. nas 원부자재발주서를 미니pc에서 편집하는데 거래처 db연결한게 업데이트가 안된다. 이유 확인 및 보완 처리 해줘.」
대상
- 파일 =
\\192.168.0.101\공유폴더\2026현장\원부자재발주서\08월\아이비젼글로벌 현대 서울숲 원부자재발주서.xlsx(26.8.27 21:14 미니PC에서 편집 중이던 것. NAS 접근은 WireGuard 터널poin필요 — 미니PC LAN 은 192.168.45.x 라 NAS 와 다른 대역) - 「거래처 DB 연결」의 실체 = 파워쿼리
업체목록Odbc.Query("dsn=pfs", "SELECT c.name … FROM pfs.company c JOIN pfs.company_member cm … WHERE remove_yn='0'")→ 「업체」 시트의 표(company_name/company_member/tel/fax/comment/address/fax_shortno7열) ※ 워크북 안에는connections.xml1건 +customXml/item1.xmlDataMashup 1건뿐. M 코드는 DataMashup[ver:4][pkgLen:4][pkg zip][permLen:4][perm][metaLen:4][meta]로 파싱해 꺼냈다.
원인 — 세 겹이 겹쳐 있었다 (엑셀은 무죄)
| # | 막힌 것 | 증거 |
|---|---|---|
| 1 | 미니PC에 MySQL ODBC 드라이버·DSN pfs 부재 |
OAlerts 21:15:33 [DataSource.Error] ODBC: ERROR [IM002] 데이터 원본 이름이 없고 기본 드라이버를 지정하지 않았습니다 |
| 2 | 미니PC 공인IP 211.177.244.214(집 회선)가 RDS SG 3306 화이트리스트 밖 |
RDS 3306 직접 프로브 = 12초 타임아웃(DROP). SG 인바운드는 사무실 112.170.234.238·PEPE phone WAN 211.209.165.141·EC2 172.31.35.211 뿐 |
| 3 | 파워쿼리 자격증명 저장소에 엉뚱한 계정 imosadmin 저장 |
OAlerts 22:22 ODBC: ERROR [HY000] … Access denied for user 'imosadmin'@'172.31.35.211' (using password: YES) — imos MSSQL 계정이 pfs MySQL 소스에 저장돼 있었다 |
사무실PC 대조군 = 같은 파일이 정상. 거기엔 64bit MySQL ODBC 8.0(8.0.18) + HKCU DSN pfs
(SERVER=RDS 엔드포인트, UID=admin, DATABASE=pfs, ANSI 드라이버 myodbc8a.dll)가 있고, 공인IP가 화이트리스트에 있다.
처리
1) ODBC 드라이버 (미니PC)
mysql-connector-odbc-26.7.1-winx64.msi 무인 설치(msiexec /qn, elevated-runner 경유).
→ MySQL ODBC 26.7 ANSI/Unicode Driver 등록. 미니PC Office = x64(ClickToRun Platform=x64)라 64bit 드라이버가 맞다.
2) 경로 — 보안그룹을 안 건드리는 쪽으로 (C:\dev\tools\rdstunnel)
엑셀 파워쿼리 → DSN pfs → 127.0.0.1:13306
→ aws ssm start-session (AWS-StartPortForwardingSessionToRemoteHost)
→ EC2 PFS-Production i-03225ba8bc12a929e (172.31.35.211 = 이미 화이트리스트)
→ poin-dbinstance…rds.amazonaws.com:3306
- SG 무변경이 핵심. 미니PC IP를 화이트리스트에 넣는 안(=ipwatch 복제)은 ①운영 DB에 집 회선 상시 노출
②
authorize-security-group-ingress= brokerAWS_HARD_DENY(텔레그램 승인 경로조차 없음) ③동적 IP 추격 → 셋 다 피했다. 회선이 바뀌어도(집·핫스팟·카페) SSM(HTTPS)이라 그대로 돈다. rdstunnel.py run= 상주 감시자. SSM 세션은 무통신 20분이면 서버가 끊으므로 5분마다 핸드셰이크 keepalive, 끊기면 재기동. 자동시작 =HKCU\…\Run\PFS-RdsTunnel→pythonw(창 없음).- DSN
pfs= HKCU,MySQL ODBC 26.7 Unicode Driver(한글 업체명 때문에 ANSI 대신 유니코드), SERVER=127.0.0.1, PORT=13306, CHARSET=utf8mb4.
3) 파워쿼리 자격증명
%LOCALAPPDATA%\Microsoft\Office\16.0\PowerQuery\User.zip 의 Credentials/Credentials.bin(DPAPI, 풀 수 없음)에
imosadmin 이 박혀 있었다 → 백업 후 제거(C:\dev\tools\rdstunnel\backup\User.zip.20260827_222445.bak).
재입력은 엑셀 GUI 1회 — 코디가 UIA로 대신 누르려 했으나 리본 메뉴 확장이 안 잡혀 페페 몫으로 남김(아래).
검증
rdstunnel.py status— supervisor pid 有 ·127.0.0.1:13306MySQL 핸드셰이크 77바이트 · DSN·자동시작 등록 확인.rdstunnel.py test— DSN 으로 발주서와 같은 쿼리 391행, 한샘·에넥스·넵스 등 한글 정상(인코딩 무손실).- 파워쿼리 경로도 EC2 를 타고 MySQL 인증 단계까지 도달함이 확인됨(=
Access denied for 'imosadmin'@'172.31.35.211'). → 자격증명만 바로잡으면 새로고침이 성립한다는 뜻. - ✅2026-08-27 22:44 페페가 자격증명 입력 완료 → 전수 반영 확인.
Credentials.bin(902B)+Firewall.xml재생성. 서로 다른 4개 파일(표준양식·08월·07월·01월) 사본을 비표시 엑셀로 새로고침 → 전부 OK(3~6초), 392행/첫행 한샘 (전 382·388·388·373행·넥서스 — 파일마다 마지막 갱신 시점이 달랐다). 392 = 헤더1+데이터391 = DB 실측과 일치. 자격증명이 박힌 뒤엔 COM 자동화로도 대화상자 없이 통과된다. - NAS 발주서 전수 스캔 = 109개 중 108개가 파워쿼리 보유, 데이터원본은 전부 동일한
dsn=pfs(표준양식 포함). 자격증명은 파일이 아니라 사용자 프로필 1곳(「전역 권한」)에 있으므로 1회 입력 = 108개 전부 적용, 파일 수정 0건. 파워쿼리 없는 1개 =02월/0219 오엠씨 발주서(에넥스 진아 공주).xlsx.
남았던 1회 작업 (페페 · 엑셀 GUI) — ✅ 2026-08-27 22:44 완료
- 발주서 열기 →
데이터→데이터 가져오기→데이터 원본 설정 전역 권한→dsn=pfs→권한 편집→자격 증명편집기본값 또는 사용자 지정그대로저장(DSN 에 계정이 이미 있음).데이터베이스탭을 쓸 거면admin/ RDS 암호확인후 새로고침(보안 알림 「외부 데이터 원본에 연결합니다」는확인) → 성공하면 「업체」 표가 391행, 첫 행이 한샘(구 넥서스)으로 바뀐다.
진단에서 배운 것 (다음에 시간 아끼려고)
- 판정은
Get-WinEvent -LogName OAlerts한 방. 엑셀이 사용자에게 띄운 대화상자 원문이 그대로 남는다.IM002(DSN/드라이버 없음) ·10060(SG DROP) ·HY000 Access denied(자격증명) — 셋은 원인이 완전히 다르다. - COM(자동화)으로 띄운 엑셀에서는 파워쿼리 오류가 전부 「다운로드하지 못했습니다.」로 뭉개진다.
진짜 사유는 OAlerts, 또는 저장 후 DataMashup 메타의
FillErrorMessage/FillStatus로 본다. GetActiveObject("Excel.Application")가MK_E_UNAVAILABLE로 막히면 창 핸들 경유가 정석 —XLMAIN > XLDESK > EXCEL7에AccessibleObjectFromWindow(OBJID_NATIVEOM).- 엑셀 모달(
NUIDialog)은 좌표 클릭이 안 먹는다(40번 눌러도 그대로) →GetInvokePattern().Invoke(). - SSH(Session 0)에서는 UNC/SMB 가 무조건 막히므로 사무실PC 원격으로 NAS 파일을 읽는 길은 없다
→ 미니PC에서 WireGuard 터널
poin을 켜고 로컬로 읽었다.
산출물
C:\dev\tools\rdstunnel\{rdstunnel.py, README.md, backup\}- 미니PC: MySQL Connector/ODBC 26.7(x64) 설치 · HKCU DSN
pfs· 자동시작PFS-RdsTunnel