[Windows] ngrok 기반 리버스 SSH 터널을 통한 원격 접속 방법

2025. 8. 27. 15:18·IT 기술

들어가며

AWS 등 방화벽 뒤에 있는 내부 서버에 접근할 일이 많은데, 밖에서 접속할 땐 허용된 IP가 아니라 접속이 불가능한 이슈가 생긴다. 그때그때 보안 그룹을 수정해 준다면 가능하지만, 그럴 권한이 없을 수도 있고 작업을 마친 뒤 보안그룹을 다시 되돌려야 하는 귀찮은 일도 생긴다.

그럴 때는 방화벽에서 허용된 IP를 통해 접속하면 이를 우회할 수 있다.

 

환경

이 게시글은 아래 환경 기반에서 작성했다.

  • 이중 NAT 환경 - 집 PC의 공인 IP로 직접 접속 불가능한 환경.
  • 집 PC - Windows 10 (방화벽 뒤 내부 서버에 접근하기 위한 터널 PC)
  • 외부 PC - MacOS Sequoia 15.5 (카페같은 외부 환경에서 접속할 PC)
  • ngrok - 무료 플랜

 

그런데, 왜 이렇게 했나?

상기 언급했듯, 이중 NAT 환경이 발목을 잡았다.

일반적으로 DDNS 혹은 포트포워딩을 통해 직접 SSH 연결을 하면 해결되는 단순한 문제지만, 이중 NAT에선 이야기가 좀 달라진다.
이중 NAT 환경에선 포트포워딩 작업을 건물 모뎀과 집 공유기 모두에서 해 주어야 한다. 건물 모뎀에선 공인 IP를 집 공유기로, 집 공유기에선 건물 모뎀으로부터 들어온 트래픽을 작업 PC에 포워딩하는 방식으로 말이다.

하지만 건물 모뎀은 건물주가 직접 관리해 접근할 수가 없어, 부득이하게 리버스 터널링으로 방향을 잡았다.

 

 

작업

5번 작업까진 모두 집 PC에서 진행한다.

1. 절전 모드 비활성화

집 밖에서 쓰려는데 터널링 PC가 절전으로 꺼져버리면 곤란해진다.

2. OpenSSH Server 설치

Windows 10/11 이상에선 기본적으로 OpenSSH Client는 설치되어 있지만, 서버는 선택 설치 사항이다. 직접 설치하자.

  • Windows 설정 - 앱 - 선택적 기능 - OpenSSH 서버
    • 시작 버튼 누르고 선택적 기능 쳐도 적당히 나온다.

이후 서비스가 켜져있는지 확인하면 된다.

Get-Service sshd

꺼져있다면 아래 명령어로 실행하자.

Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

3. 방화벽 설정 확인

SSH 포트인 22번 포트가 열려 있어야 한다.
직접 방화벽을 손봐도 되지만, 명령어로 깔끔하게 하자. 안 된다면 관리자 권한으로 Powershell을 열었는지 확인하자.

New-NetFirewallRule -Name sshd -DisplayName "OpenSSH Server (sshd)" -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

이제 아래 명령어로 포트가 잘 열려있는지 확인한다.

netstat -an | findstr :22

포트 상태가 LISTEN이 아니라면 뭔가 문제가 생긴 것이다. GPT나 퍼플렉시티 등에게 물어보도록 하자.

 

4. SSH 키 준비

4-1. SSH 키 생성

ssh-keygen -t ed25519 -C "설명이나 이름"

"-C" 옵션은 키를 구분할 주석(PC명, 이메일 등)을 붙이는 것으로, 설명이나 이름은 알아서 적도록 하자.
명령어 입력 시 저장 경로와 패스프레이즈를 입력하라고 한다. 저장 경로를 물을 때 경로 없이 엔터치면 기본 경로(~/.ssh/)로 간다.
ED25519 대신 RSA(4096비트)를 원한다면, 아래 명령어로 진행하면 된다.

ssh-keygen -t rsa -b 4096 -C "설명"

 

이번엔 PublicKey 에러로 튕겨나가는 걸 막기 위한 SSH 키 권한을 잡아보자.
일반적으로는 chmod 700 ~/ssh로 해결 가능하지만, 여긴 윈도우라 그런게 없다. 아래 명령으로 해결하자.

$sshFolder = "$env:USERPROFILE\.ssh"
icacls.exe $sshFolder /inheritance:r
icacls.exe $sshFolder /grant:r "$($env:USERNAME):(F)"
icacls.exe $sshFolder /remove "Users" "Everyone"

 

뭔가 문제가 생긴 듯 하다면, 관리자 권한으로 Powershell을 켰는지 확인하자.
여기까지 마쳤다면, 외부 PC(노트북)의 ~/.ssh에 지금 만든 key를 저장하기 위해 개인 Discord나 카카오톡 나에게 보내기 등을 활용해 미리 준비하는 게 좋겠다.

 

4-2. 공개키 등록

생성한 공개키 내용을 집 PC (연결할 대상)의 ~/.ssh/authorized_keys에 등록해야 한다.

cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys

 

마찬가지로 authorized_keys 파일에도 권한을 설정해야 한다.
역시나 chmod 600 ~/.ssh/authorized_keys로 해결할 수 있겠지만, 여긴 윈도우다.

$authKeys = "$env:USERPROFILE\.ssh\authorized_keys"
icacls.exe $authKeys /inheritance:r
icacls.exe $authKeys /grant:r "$($env:USERNAME):(R,W)"
icacls.exe $authKeys /remove "Users" "Everyone"
  • PowerShell에서 환경 변수 $env:USERPROFILE은 사용자 홈 디렉토리를 가리킨다.

 

5. ngrok

5-1. ngrok 설치

https://ngrok.com

위 환경에서 각자에게 맞는 ngrok을 설치한다. 이 글에서는 Windows 10 x64가 되겠다.

5-1-1. ngrok 가입 (Optional)

ngrok 가입 후 Authtoken 설정을 안 하면 세션 연결이 8시간 뒤에 끊긴다고 하더라.
굳이 상관 없다면 이 단락은 넘기고 5.2로 가자.

필요하다면 가입한 후, Authtoken을 찾아 집 PC에 등록하자.

ngrok config add-authtoken $YOUR_AUTHTOKEN

 

명령어를 입력하면, 어떤 경로에 설정 정보가 저장되었다고 나온다. (ex: C:\Users\[USERPROFILE]\AppData\Local/ngrok/ngrok.yml) 근데 본인은 저 위치에 저장된 파일이 없어서 굉장히 이상하지만, 아무튼 잘 되니까 넘어가도록 하자.


관련 설정 파일은 ngrok config check, ngrok config edit 등 활용 가능하다.

관련 내용은 공식 페이지를 참고하자.

 

5-2. ngrok 실행

ngrok tcp 22

 

SSH를 여는 게 목표니, tcp 22로 열자. 웹서버나 기타 포트 관련 방법은 다루지 않고 넘어간다.

 

실행하면 대략 저런 모습으로 나온다. 저기에서 우리가 필요한 정보는 Forwarding의 Host와 Port만 알면 된다.
여기에선 Host: 0.tcp.jp.ngrok.io, Port: 16704다.

참고로 무료 플랜에서 ngrok을 껐다 키면 포트가 변경된다.

 

6. 외부 PC 설정

이제 외부 PC에서 작업할 차례다.

6-1. SSH Key 저장

4-1 단계에서 생성한 SSH Key를 ~/.ssh에 저장하자. 이름은 딱히 상관 없으니 필요하다면 변경하자.

6-2. SSH 연결

지금까지 잘 따라왔다면, ssh -p [PORT] [USERNAME]@[HOST] -i [SSH 키 경로]로 접속 가능하다.
PORT와 HOST는 직전에 언급했고, USERNAME을 모른다면 집 PC에서 cmd를 열어보자. (관리자 권한 X)

C:\Users\[USERNAME]>

 

이런 식으로 나타날텐데, 저 USERNAME이 집 PC에서 지금 사용하는 사용자 이름이다.
SSH 키 경로는 ~/.ssh에 저장한 키 파일 경로다.

 

publicKey 문제가 발생한 경우, 여기에선 마음 편히 chmod 600으로 해결하면 되겠다.
디렉토리에 설정하는 경우엔 chmod 700으로 하면 된다.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa          # 개인키
chmod 600 ~/.ssh/authorized_keys # 서버측 공개키 리스트 파일

참고하도록 하자.

6-1-1. SSH config 설정 (Optional)

매번 저 긴 ssh 명령어 를 입력하는 건 조금 번거롭다. ~/.ssh에 config 파일을 만들자. (~/.ssh/config)

Host ngrok-home
    HostName [HOST]
    User [USERNAME]
    IdentityFile [SSH 키 경로]

 

위 값을 적절히 수정해 저장하자.

포트까지 고정하려면 HostName, User 등과 같은 들여쓰기 레벨에서 Port ???? 로 지정하면 되나, 우리는 포트가 항상 바뀔 것을 염두해야 하므로 생략한다. ngrok-home 대신 다른 이름을 사용해도 되나, 아래 명령어 사용 시 그 이름으로 바꾸어 입력하자.

 

이제 기존의 그 긴 명령어를 치는 대신, 아래 명령어로 간략하게 보낼 수 있다.

ssh ngrok-home -p [PORT]

 

TroubleShooting

1. Permission denied (publickey)

외부 PC의 권한 문제다. chmod 600 [ssh key path]로 해결하자.
그래도 안 된다면, 집 PC의 ~/.ssh/authorized_keys에 있는지 점검하자.

혹은 관리자 권한으로 집 PC에서 OpenSSH를 열어서 디버그 모드로 확인하자.

C:\Windows\System32\OpenSSH\sshd.exe

 

디버그 모드인 경우에는 기존 authorized_keys 파일 대신 __PROGRAMDATA__/ssh/administrators_authorized_keys에 접근하는 경우가 있는데, 관련 문제는 GPT나 퍼플렉시티, 혹은 검색으로 해결하자. 필자는 이 문제가 발생했으나 그냥 서비스로 돌려 실행하니 해결되었다.

 

2. 연결 시도 즉시 연결 끊김

집 PC(호스트)의 SSH 서버가 꺼져 있다.

Get-Service sshd

위 명령어로 실행 여부를 확인하자. 꺼져있다면 아래 명령으로 시작하자.

Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

별도로 SSH 서버가 예기치 않게 종료되어도 자동으로 재시작할 수 있는 방법이 있다.

sc.exe failure sshd reset= 86400 actions= restart/5000

[SC] ChangeServiceConfig2 성공 이 나오면 정상적으로 된 것이다.

설정이 제대로 적용되었는지 확인은 아래 명령으로 한다.

sc.exe qfailure sshd
[SC] QueryServiceConfig2 성공

SERVICE_NAME: sshd
        RESET_PERIOD (in seconds)    : 86400
        REBOOT_MESSAGE               :
        COMMAND_LINE                 :
        FAILURE_ACTIONS              : 다시 시작 -- 지연 = 5000밀리초.

 

대략 이런 식의 출력이 보이면 잘 설정되었다.

References

https://jybaek.tistory.com/798
https://innerjoin.tistory.com/25#Ngork%20Authtoken%20%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0-1
https://ngrok.com/docs/agent/config/

'IT 기술' 카테고리의 다른 글

[EC2] AWS EC2에 네트워크 트래픽 스파이크와 CPU 크레딧소모로 인한 서버 다운 해결 방법  (2) 2025.08.28
[Mac] Access denied for user 'root' @'localhost ' (using password: YES) 오류 해결  (0) 2025.08.20
npm run dev 시 EACCES: Permission Denied 포트 충돌 해결방법  (0) 2025.07.13
구글 시트를 활용한 홈페이지 폼 데이터 수집 시스템 구축하기  (0) 2025.06.21
AWS Eventbridge 일정으로 여러 Lambda 동시에 실행하기  (0) 2025.04.11
'IT 기술' 카테고리의 다른 글
  • [EC2] AWS EC2에 네트워크 트래픽 스파이크와 CPU 크레딧소모로 인한 서버 다운 해결 방법
  • [Mac] Access denied for user 'root' @'localhost ' (using password: YES) 오류 해결
  • npm run dev 시 EACCES: Permission Denied 포트 충돌 해결방법
  • 구글 시트를 활용한 홈페이지 폼 데이터 수집 시스템 구축하기
시남
시남
개발하는 사람입니다. 하고 싶은 것들 사이에서 매번 선택하는 삶을 살고 있습니다.
  • 시남
    Refactor Life like code.
    시남
  • 전체
    오늘
    어제
    • 분류 전체보기 (22)
      • IT 기술 (10)
        • Spring boot (5)
      • 이야기 (3)
      • 독서 (0)
      • 개발일기 (4)
        • 1D3Q (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    1D3Q
    reverse tunnel
    프롬프트 엔지니어링
    h2-console
    개발일지
    h2 콘솔
    root@localhost
    gradle-wrapper
    gemini
    vibe coding
    H2DB
    contentcachingrequestwrapper
    코드 하이라이팅
    1인개발
    Spring
    Spring Boot
    ai 검색
    java
    기획
    1인기획
    springboot h2
    사이드프로젝트
    h2 console
    AWS
    회고
    bootrun
    로켓방정식의 저주
    바이브코딩
    리버스 터널링
    Ai
  • 최근 댓글

  • 최근 글

  • hELLO By정상우.v4.10.4 관리
시남
[Windows] ngrok 기반 리버스 SSH 터널을 통한 원격 접속 방법
상단으로

티스토리툴바