로컬에 있는 서버를 공개하는 것은 쉬운 일이 아니죠. 특히 CGNAT 환경, 또는 공용 인터넷을 활용해야 하는 경우라면 더 그렇습니다. 원하는 대로 포트포워딩을 못 하기 때문이죠.
이를 해결하기 위해 터널링을 활용하곤 합니다. http/https만 뿌리면 되는 웹서버라면 Cloudflare tunnel같은 걸 쓸거고, 다양한 포트가 필요하다면 ngrok같은걸 쓰겠죠. VPS가 있으면 Wireguard 설정도 가능합니다.
하지만 우리 해커들은 http/https만 지원하는 Cloudflare가 마음에 들 리가 없습니다. ngrok은 유료플랜을 쓰는 게 아닌 이상 지속적으로 활용하기 애매하고요. CGNAT 환경에서는 Wireguard 연결도 어렵습니다(되는걸로 알고 있긴 한데 좀 삽질이 필요할겁니다)
그래서 저는 한동안 Tailscale을 썼습니다. CGNAT 환경에서 매우 합리적인 선택지이죠. 그러나 Tailscale도 나름의 단점이 많습니다.
우선 Tailscale은 컴퓨터들을 tailnet이라는 분리된 서브넷에 넣어주는 방식이므로, 기본적으로 외부 포트 공개가 목적이 아닙니다. 내 컴퓨터끼리 쉽게쉽게 SSH하기 위한 툴이에요. 그래서 VPS를 하나 마련해 nginx같은 리버스 프록시를 설정해야 하는 번거로움이 있죠.
게다가 연결할 서버를 모두 tailnet에 등록해야하는 것도 불편합니다. 물론 라즈베리파이나, LXC같은걸 돌려서 그걸 tailnet의 subnet router로 쓰는 것도 가능합니다. 그러면 다음과 같은 구조가 나오겠죠.
인터넷 -> VPS -> 로컬 라즈베리파이(subnet router) -> 로컬 서버
이런 벌써부터 머리가 아픕니다.
제가 이렇게 대략 2달동안 돌렸습니다. 분명 잘 돌아가지만, 귀찮은 게 한두개가 아닙니다.
우선 저는 nginx 쓰는 데 자신이 없기에, VPS에서 도커로 nginx-proxy-manager를 씁니다. 그말은? 포트 하나 열려고 하면 헬게이트가 열리는거죠.
VPS 설정에서 포트 열고, 방화벽에서 포트 열고, 도커 포트 추가해서 다시 빌드하고, nginx proxy manager 페이지 들어가서 포트 스트림 등록하고. 이걸로 되면 참 좋겠지만 늘 뭔가 문제가 생기죠.
아주 미쳐버립니다. AWS에 현질하는게 편하지 않나라는 생각이 끊임없이 듭니다.
그러던 어느날, frp라는 프로젝트를 발견했습니다. 오픈소스고, 스타도 많고, ARM 아키텍쳐도 지원하고, 읽어보니 configuration도 상당히 쉬워 보였습니다. 무엇보다도, 다음 이미지가 특히 이목을 끌었습니다.

이런 세상에, 제가 사용하던 구조와 거의 동일합니다. Public ip를 가지는 frps는 VPS 서버가 하면 되는거고, frpc는 라즈베리파이가 하면 됩니다. tcp/http 서비스는 로컬 주소를 그대로 활용하면 되구요. 따라서 바로 체험해보도록 했습니다.
frps(서버) 설치 및 세팅
frp는 frps(서버)와 frpc(클라이언트)로 나뉩니다. 우선 VPS에서 서버 먼저 설정해보기로 했습니다.
# 최신 frp 릴리즈 다운로드. 저는 arm 기반의 VPS를 썼기에 arm을 한겁니다.
wget https://github.com/fatedier/frp/releases/download/v0.65.0/frp_0.65.0_linux_arm64.tar.gz
# 압축 해제
tar -zxvf frp_0.65.0_linux_arm64.tar.gz
# 실행 파일을 시스템 경로로 이동
sudo mv frp_0.65.0_linux_arm64/frps /usr/bin/
# 설정 파일 디렉토리 생성
sudo mkdir /etc/frp
# 기본 설정 파일 이동
sudo mv frp_0.65.0_linux_arm64/frps.toml /etc/frp/
# 필요 없는 파일 삭제
rm -rf frp_0.65.0_linux_arm64*
신생 프로젝트라 그런지 공식 데비안 패키지 레포에 없는 건 좀 아쉽지만 이정도면 간단해서 좋습니다.
VPS 세팅하는거니, 여기서 중요한 것은 실행파일 /usr/bin/frps와 설정파일 /etc/frp/frps.toml이겠네요.
설정파일인 /etc/frp/frps.toml부터 건드려봅시다
bindPort = 7000
auth.token = "YourStrongSecretTokenHere"
bindPort는 frps가 frpc와 통신할 때 사용되는 포트로, 7000이 기본값인 듯 합니다.
이 설정만으로는 아무나 frpc를 걸어버릴 수 있으니 auth.token에 PSK 토큰을 설정하세요. 저는 bitwarden으로 무작위 생성해서 메모해뒀습니다.
한번 테스트해봅시다:
$ /usr/bin/frps -c /etc/frp/frps.toml
2025-10-11 13:52:40.803 [I] [frps/root.go:108] frps uses config file: frps.toml
2025-10-11 13:52:41.792 [I] [server/service.go:236] frps tcp listen on 0.0.0.0:7000
2025-10-11 13:52:41.792 [I] [frps/root.go:117] frps started successfully
-c 옵션을 통해 옵션파일을 명시적으로 넘겨줄 수 있습니다. 우선 잘 실행되는 것으로 보입니다. 이제 서버가 재부팅되어도 자동으로 실행되도록, systemd 서비스를 설정합니다.
sudo nano /etc/systemd/system/frps.service
[Unit]
Description=FRP Server
After=network.target
Wants=network.target
[Service]
Type=simple
User=nobody
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frps -c /etc/frp/frps.toml
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
# systemd 데몬 리로드
sudo systemctl daemon-reload
# 부팅 시 자동 시작 활성화
sudo systemctl enable --now frps
방화벽 및 포트포워딩 설정에서 7000번 포트와 여러분들이 사용할 다른 포트까지 열면 frps는 설정 끝입니다.
frpc(클라이언트) 설치 및 설정
이제 frpc를 라즈베리파이에 설치해주었습니다. 기본적으로 frps와 똑같습니다.
# 최신 frp 릴리즈 다운로드. 저는 arm 기반인 라즈베리파이를 썼기에 arm을 한겁니다.
wget https://github.com/fatedier/frp/releases/download/v0.65.0/frp_0.65.0_linux_arm64.tar.gz
# 압축 해제
tar -zxvf frp_0.65.0_linux_arm64.tar.gz
# 실행 파일을 시스템 경로로 이동
sudo mv frp_0.65.0_linux_arm64/frpc /usr/bin/
# 설정 파일 디렉토리 생성
sudo mkdir /etc/frp
# 기본 설정 파일 이동
sudo mv frp_0.65.0_linux_arm64/frpc.toml /etc/frp/
# 필요 없는 파일 삭제
rm -rf frp_0.65.0_linux_arm64*
이제 frpc의 설정파일인 /etc/frp/frpc.toml을 이런식으로 설정하면 됩니다:
serverAddr = "<frps 서버 주소>"
serverPort = 7000
auth.token = "YourStrongSecretTokenHere" # frps.toml과 동일한 토큰
[[proxies]]
name = "minecraft"
type = "tcp"
localIP = "192.168.1.101"
localPort = 25565
remotePort = 25565
[[proxies]]
name = "terraria"
type = "tcp"
localIP = "192.168.1.102"
localPort = 7777
remotePort = 7777
마찬가지로 systemd 서비스를 다음과 같이 설정하면 됩니다:
sudo nano /etc/systemd/system/frpc.service
[Unit]
Description=FRP Client
After=network.target
[Service]
Type=simple
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/frpc -c /etc/frp/frpc.toml
ExecReload=/usr/bin/frpc reload -c /etc/frp/frpc.toml
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
# systemd 데몬 리로드
sudo systemctl daemon-reload
# 부팅 시 자동 시작 활성화
sudo systemctl enable --now frpc
재부팅하고 나면 완벽하게 될겁니다.
만약 안된다면 방화벽, 경로명, IP 등을 다시 확인해보세요.
총평
그동안 Tailscale이랑 NPM 때문에 너무너무 고생했는데, 정말 편하고 좋습니다…
나만의 ngrok이 생긴 것 같네요. 활용도는 정말 무궁무진할 것 같습니다. 듣기로는 해커들이 리버스쉘 만들 때에도 활용? 악용한다고 하네요. 그 정도로 유용한 것 같습니다.