[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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바