어느 가정집에서나 쉽게 볼 수 있는 LAN
구성이다. 이를 통해 Home Router
를 통한 Port Forwarding
, 그리고 Nginx
를 통한 Reverse Proxy
설정 방법에 대해 기술하려 한다.
시작에 앞서 LAN
구성에 대해 간단하게 소개하고 또 왜 이러한 설정이 필요한지 서술하려 한다. 위의 도식은 필자의 집안 꼴을 아름답게 추상화한 다이어그램이다. 실재의 장치 구성은 앞선 Preview 삽화와 같다.
또한 우측의 개인 컴퓨터 (PC)
와 ODROID N2+
의 SSH Tunneling
은 그리 중요한 사항이 아니므로 이하의 Gitlab (Web)
과 Nginx with Cloud Storage (Web)
부분만 잘 들여보길 바란다.
Port Forwarding
is needed? Public IP
를 할당받은 Home Router
는 연결된 각 장치에 대해 Private IP
를 할당해주고, 이들은 외부로 통신하기 위해 Home Router
를 거친다.
내부에서 외부로 나가는 요청은 Home Router
가 요청에 따른 NAT Table
을 유지 및 구성하기 때문에 데이터를 주고 받는데 별다른 문제가 발생하지 않으나, 외부에서 내부로 들어오는 요청은 그 얘기가 달라진다.
외부에서 내부로 들어올 때에는 요청 주소와 내부 장치 간 매핑이 제대로 이뤄지지 않았기 때문에 패킷이 정확한 목적지로 전달되지 않는다. 따라서 아무런 설정없이 공유기를 거쳐 서버를 열게 되면 외부에서 들어오는 클라이언트의 요청을 받을 수 없게 된다. 따라서 외부 요청에 따른 내부 장치에 대한 매핑을 수행해야 하며 이를 Port Forwarding
이라 부른다.
그럼 위 도식에서는 왜 Nginx
를 사용하였을까? Port Forwarding
을 통해 외부에서 접속하는 것은 가능하나, 문제는 일부 프로토콜이 통신에 사용하는 포트 번호를 예약(e.g. SSH
는 22
, HTTP
는 80
) 했기 때문에 같은 서비스를 구축하는 경우 포트 번호가 겹치는 상황이 발생할 수 있다. 위 도식을 보면 알겠지만 같은 네트워크 상에서 웹 서버를 동시에 두 개나 실행하고 있으며 HTTP(S) Protocol
에 사용되는 포트 번호는 이미 예약 되어 있다.
물론 포트 번호를 나눠서 사용해도 된다. 예약되어 있다는 것이지 다른 포트의 사용이 불가능하진 않기 때문이다. 그러나 이 경우에는 URL 에 포트번호를 직접 명기해야 한다. 이는 그리 바람직한 해결책이 아니다.
그러므로 요청한 도메인 주소에 따라 그 요청을 처리할 장치 및 애플리케이션을 지정해 줄 필요가 있다. 이는 네트워크 장비 측에서 수행 가능한 동작은 아니고 (실제로 L7 네트워크 장비
가 있으나 생략) Application Layer
에서 이뤄져야 하는 동작이다.
최종적으로 Home Router
로 전달되는 모든 외부의 HTTP(S)
요청은 Port Forwarding
을 통해 Nginx
가 동작하는 장비로 forward
된다. 이후 Nginx
는 요청한 domain
을 parse
하여 적절한 장치 혹은 적절한 애플리케이션으로 그 요청을 forward once more
한다.
Port Forward
by Router집에서 공유기를 사용하고 있다면 이하의 명령어를 입력하여 공유기의 주소를 확인할 수 있다:
ip route
Router
설정 페이지 이동 게이트웨이의 주소가 192.168.176.1
이라는 것이 확인 되었다. 대부분의 공유기는 공유기 자체가 서버로 동작하면서 네트워크 관련 설정을 웹에서 수행 가능하게 만들었다. 따라서 위 주소를 브라우저에 입력하여 접속하게 되면 라우터 관리자 페이지로 이동할 수 있게 된다. (아래 페이지와 터미널 결과 주소가 조금 다른데 아마 WSL
환경이라 그런 것 같다, Windows Powershell
에서 netstat
을 찍어보면 제대로 나온다.)
접속하면 위와 같은 화면을 볼 수 있다. 네트워크 장비마다 화면 구성이 서로 상이할 수 있으나 이들이 하는 역할은 크게 다르지 않다.
여기에서 네트워크 장비를 선택한 뒤 로그인(보통 네트워크 장비 뒤에 초기 비밀번호가 적혀 있다) 하게 되면 다음과 같은 화면을 볼 수 있다. 필자는 입맛에 맞게 장치 설정을 변경했으나 통신사 장비라면 통신사 명과 장치 일련 번호 등으로 구성된 SSID
등을 확인할 수 있다.
Port Forwarding
Port Forwarding
은 NAT 설정
에서 가능하다.
위와 같이 서비스 포트
와 프로토콜
을 지정하면 라우터는 공인 IP:서비스 포트
를 통해 전달받은 모든 외부의 요청을 IP 주소(사설 IP):내부 포트
로 Forward
(전달하다) 해준다.
Nginx
Nginx
는 대중적으로 많이 사용 되어지고 있는 웹 서버이다. 그런데 그냥 웹 서비싱만 해주는 것은 아니고 아래에서 소개할 Reverse Proxy
, 더 나아가 Load balancing
, Caching
과 같은 기능들도 수행 가능하다.
Nginx
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
apt
패키지 매니저를 사용하는 배포판에서의 설치판인데 보통 다 존재하므로 nginx
입력하고 설치하면 자동으로 설치가 진행된다.
Nginx
touch /etc/nginx/sites-available/<filename>.conf
ln -s /etc/nginx/sites-available/<filename>.conf /etc/nginx/sites-enabled/<filename>.conf
위 명령어를 입력하여 sites-available
그리고 sites-enabled
디렉토리에 설정 파일을 생성하고 연결한다. 이제 아래의 내용을 설정 파일 내에 기록한다.
log_format <your format> $http_x_forwarded_for $remote_addr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_response_time';
server {
listen 80;
server_name <your domain>;
rewrite ^ https://$http_host$request_uri? permanent; # Forced redirect from HTTP to HTTPS
server_tokens off; # Prevents the Nginx version from being displayed in the HTTP response header
}
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/<your sites certkey>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<your sites certkey>/privkey.pem;
server_name <your domain>;
server_tokens off;
location / {
proxy_pass <proxy pass>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_read_timeout 1200s;
proxy_set_header X-Forwarded-Proto https;
# used for view/edit office file via Office Online Server
client_max_body_size 0;
access_log /var/log/nginx/<name>.access.log <your format>;
error_log /var/log/nginx/<name>.error.log;
}
}
<your format>
, <your domain>
, <your sites certkey>
, <proxy pass>
, 그리고 <name>
은 독자 여러분이 직접 채워 넣어야 한다. 변경된 설정은 아래의 명령어를 입력하여 재적용이 가능하다.
sudo nginx -t
sudo nginx -s reload
혹시 HTTPS
를 위한 Certificate Key
가 생성되지 않아 에러가 발생한다면 아래의 섹션을 읽고 다시 설정파일을 적용 시키면 된다.
위 <certkey>
항목은 Certbot
으로 생성이 가능하고, Certbot
은 다음을 통해 설치가 가능하다. 설치가 끝났다면 아래의 명령어를 입력하여 HTTPS
접속을 위한 보안키를 생성할 수 있다.
sudo certbot certonly --nginx
처음에 선택 가능한 도메인이 나타나지 않는다면 위 설정 파일의 HTTPS
server
파트만 지운 상태로 작업한 뒤 nginx
를 reload
하면 선택 가능 항목이 나온다. 도메인에 대한 certificate key
가 생성되었다면 다시 HTTPS
관련 파트를 복구한 뒤 다시 nginx
를 reload
한다.
위 설정을 통해 <your host>
로 전달되어지는 모든 요청들을 <your domain>
로 넘길 수 있다. 위에서 소개한 Home Router
의 Port Forwarding
그리고 Nginx
를 이용한 Reverse Proxy
설정만 알아도 하나의 Public IP
를 통해 동시에 여러 개의 서비스를 굴리는 것이 가능해진다.
[도식] https://draw.io/
[이미지] https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html
[이미지] https://en.wikipedia.org/wiki/Nginx
[사이트] https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
[사이트] https://certbot.eff.org/
[이미지] https://www.herlitz.io/2022/03/27/running-optimizely-cms-behind-nginx-reverse-proxy/