이번 글은 Tailscale을 이용한 네트워크 연결 확인부터 파이썬을 활용한 웹 서버 구동에 대해 정리한 글입니다.
이전 글에서는 라즈베리파이(서버)에 Tailscale을 설치하고, 가상 네트워크로 내 장비들을 연결하고 SSH 접속 테스트까지 진행했었다. 이번 글을 보기 전에 세팅이 되어있지 않다면, 아래 글을 먼저 확인하는 것을 추천한다.
[Infra][SSH] 이중 NAT 환경에서 포트포워딩 없이 외부에서 라즈베리파이 접속하기 (with. Tailscale)
[Infra][SSH] 이중 NAT 환경에서 포트포워딩 없이 외부에서 라즈베리파이 접속하기 (with. Tailscale)
이 글인 이중 NAT 환경에서 포트포워딩 없이 터널링을 이용하여 외부에서 라즈베리파이에 SSH로 접속하는 방법에 대해 정리한 글입니다.개발 환경기기 정보모델 : Raspberry Pi Zero WOS : Raspberry Pi OS Li
devkuk.tistory.com
네트워크 연결 상태 확인하기
먼저 서버(라즈베리파이)와 내 PC가 같은 가상 네트워크(Tailnet) 안에 들어와 있는지 확인해야 한다.
SSH로 서버에 연결하고, SSH 터미널에 아래 명령어를 입력한다.
tailscale status
이 명령어를 입력하면, 현재 내 계정에 연결된 기기 리스트와 각 기기의 Tailscale IP가 나타난다. 일반적으로 100.xxx.xxx.xxx 형태의 주소를 가진다.
💡 Tailscale IP란?
Tailscale은 전 세계 어디에 있든 내 기기들을 하나의 가상 네트워크로 묶어준다. 이때 부여되는 100.xxx.xxx.xxx 주소는 일반적인 공유기 내부 IP(192.168.xxx.xxx)와 달리 Tailscale이 설치된 기기 사이에서만 통용되는 전용 주소이다. 이 주소 덕분에 포트포워딩 없이도 안전하게 통신할 수 있다.
Ping 테스트
같은 가상 네트워크에 연결되어 있는 것을 확인한 후, 두 기기가 물리적으로 떨어져 있어도 대화가 가능한지 확인하기 위해 ping을 보내볼 차례이다.
메인 PC에서 터미널(Windows의 PowerShell 또는 Mac의 터미널)을 열고, 서버 Tailscale IP로 핑을 날려본다.
# 예시: ping 100.123.45.67
ping <라즈베리파이_Tailscale_IP>
이때 응답(Reply)이 정상적으로 온다면, 두 기기 사이에 암호화된 터널이 완벽하게 생긴 것이다.

💡 Ping과 ICMP 프로토콜
일반적으로 데이터 전송에서는 TCP나 UDP를 사용한다. 하지만 ping 명령어는 TCP나 UDP가 아닌 ICMP(Internet Control Message Protocol)라는 별도의 프로토콜을 사용한다.

ICMP는 TCP/IP 모델에서는 인터넷 계층(Internet Layer), 그리고 OSI 7계층 모델에서는 네트워크 계층(Network Layer, 3계층)에 속하며, 이는 IP와 동일한 계층에 속하는 프로토콜이다.
ICMP는 데이터를 나르는 것이 아니라 네트워크의 상태를 진단하고 오류를 보고하는 역할을 하며, ping 명령어는 ICMP의 Echo Request(요청)와 Echo Reply(응답) 메시지를 사용한다.
간이 웹 서버 띄우기
연결을 확인했으니, 복잡한 설정 없이 간단하게 파이썬 기본 모듈(http.server)을 활용해 웹 서버를 동작시켜 보자.
먼저 테스트용 폴더를 생성하고, 해당 폴더로 이동한다. (모든 명령은 서버 터미널에서 실행한다.)
mkdir web_test
cd web_test
그리고 간단하게 index.html 파일을 생성한다.
echo "<h1>Hello from Ubuntu Server 24.04 LTS via Tailscale.</h1>" > index.html
파일 생성이 완료되면, 8000번 포트로 웹 서버를 실행한다.
python3 -m http.server 8000
서버가 실행되면 터미널에서는 로그가 찍힐 준비를 한다.

서버가 아닌 외부 PC(본인의 Tailscale 그룹에 등록되어 있는 기기)에서 브라우저를 열고 주소창에 아래와 같이 입력한다.
http://<서버_Tailscale_IP>:8000
# 예시: http://100.123.45.6:8000
인터넷 접속에 성공하면, 서버 터미널에는 접속 로그가 남고 브라우저에서는 위에서 만든 index.html의 내용이 출력된다.


💡포트(Port)란 무엇인가?
IP 주소가 건물의 도로명 주소라면, 포트 번호는 그 건물 내부의 방 번호와 같다. 프로그램이나 프로토콜에 따라 일반적으로 사용하는 포트가 서로 다르다.
- 22번 포트: 원격 접속 (SSH)
- 80번 포트: 일반적인 웹 서비스 (HTTP)
- 443번 포트: 일반적인 웹 서비스 (HTTPS)
특정 서비스에 접속하기 위해서는 반드시 해당 서비스가 열려 있는 포트를 주소 뒤에 명시해야만 한다. (ex. 123.456.78.9:8000)
💥 400 Bad Request
HTTP(HyperText Transfer Protocol) 400 Bad Reqeust 응답 상태 코드는 서버가 클라이언트 오류를 감지해 요청을 처리할 수 없거나, 하지 않는다는 것을 의미한다.
- 잘못된 요청 구문 | 유효하지 않은 요청 메시지 프레이밍 | 변조된 요청 라우팅 등
400 Bad Request는 다양한 원인에 의해서 발생할 수 있지만, 위 과정을 따라하다가 이 에러를 발견했다면, 아마도 http://와 https://의 차이에 의해 발생했을 것이다. 즉, 서버와 클라이언트가 서로 다른 프로토콜로 요청와 응답을 주고받으려고 시도 했기 때문이다.
브라우저는 기본적으로 보안을 위해서 https://로 접속을 시도하지만, 파이썬의 http.server 모듈로 띄운 서버는 보안 기능이 없는 매우 단순한 서버였기 때문에 https://를 지원하지 않으면서 해당 오류가 발생하게 되는 것이다.
💡 HTTP vs HTTPS
HTTP와 HTTPS의 차이는 인프라 보안의 핵심이다.
- ✉️ HTTP (HyperText Transfer Protocol)
- 비유: 내용을 누구나 읽을 수 있는 "엽서"
- 특징: 데이터가 암호화되지 않은 평문(Plain Text)으로 전송된다. 중간에 누군가 패킷을 가로채면(Sniffing) 아이디나 비밀번호를 그대로 볼 수 있어서 보안에 취약하다.
- 포트: 기본적으로 80번을 사용한다.
- 🔒 HTTPS (HTTP over Secure Socket Layer)
- 비유: 튼튼한 자물쇠가 채워진 "강철 금고"
- 특징: HTTP에 SSL/TLS라는 암호화 계층을 덧씌운 프로토콜이다. 데이터를 보내기 전에 암호화하고 받는 쪽에서 복호화한다. 중간에 가로채더라도 암호를 풀 수 없어서 내용을 알 수 없다.
- 포트: 기본적으로 443번을 사용한다.
SSL과 TSL
흔히 SSL이라고 부르지만, 현재는 보안이 더 강화된 TLS(Transport Layer Security)라는 명칭이 표준이다. HTTPS는 통신 경로 자체를 암호화하여 데이터의 기밀성(내용 보호)과 무결성(변조 방지)을 보장한다.
'🖥️ Dev > Infra' 카테고리의 다른 글
| [Infra][Docker][Error] docker: Error response from daemon: unauthorized (0) | 2026.02.08 |
|---|---|
| [Infra][Docker] 도커 네트워크로 백엔드와 DB 연동해서 배포하기 (0) | 2026.02.04 |
| [Infra][SSH] 이중 NAT 환경에서 포트포워딩 없이 외부에서 라즈베리파이 접속하기 (with. Tailscale) (0) | 2026.01.23 |
| [Infra][Docker] 도커 이미지 이해하기 (1) | 2025.07.20 |
| [Infra][Docker] 도커 기본 명령어 모음 (0) | 2025.07.20 |
since 2025.01.27. ~ 개발자를 향해....🔥