들어가며
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 설치
위 환경에서 각자에게 맞는 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 |