배경
프로젝트를 서버에 배포하고 실행한 후 접속을 시도했을 때 SocketException: Permission denied 에러가 발생했다. 이 에러는 애플리케이션이 특정 포트에 바인딩하려고 할 때 권한이 없어 발생하는 문제라고 한다. 원인과 어떻게 해결할 수 있는지 확인해보자
Caused by: java.net.SocketException: permission denied at
sun.nio.ch.Net.bind0(Native Method) at
sun.nio.ch.Net.bind(Net.java:461) at
sun.nio.ch.Net.bind(Net.java:453) at
sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) at
org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:276) at
org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:231) at
org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1324) at
org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1410) at
org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:663) at
org.apache.catalina.connector.Connector.startInternal(Connector.java:1039) ... 28 common frames omitted
개발 환경
- CentOS 7
- Tomcat
- Java 1.8
- Spring Boot 2.7
원인
Linux는 일반 사용자에게 1024번 미만 포트에 대한 권한을 주지 않는다. 0 ~ 1023번 포트는 잘 알려진 포트(Well-known ports)로 분류되어, root 권한이 필요하다.
이 문제를 해결하기 위한 여러 방법 중 sudo 명령어 사요이나 root 계정으로의 실행은 보안 위험이 있어 제외했다.
setcap 방식도 있었지만 본 프로젝트에서는 firewall 포트 포워딩 방법을 선택했다. 이 방식은 애플리케이션이 기존 포트 번호를 유지하면서도 외부에서 http 포트로 접근할 수 있도록 해준다. 또한 한 곳에서 포트 권한을 관리하기 때문에 유지보수성과 보안성이 높았다.
해결
포트 포워딩이란 특정 포트로 들어오는 트래픽을 다른 포트로 전달하는 매커니즘이다. 일반적으로 웹 서버나 프록시 서버를 통해 사용된다.이를 통해 클라이언트가 80 포트로 요청을 보내면 실행중인 포트로 전달해서 애플리케이션에 접근 가능하다. CentOS에서 Firewall(방화벽)을 통해 설정을 진행했다.
// 외부에서 들어오는 80 포트 트래픽을 지정한 포트로 전달하도록 설정
$ firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 --permanent
success
// 로컬에서 발생하는 80 포트 요청을 지정한 포트로 전달하도록 설정
$ firewall-cmd --permanent --direct --add-rule ipv4 nat OUTPUT 0 -p tcp -o lo --dport 80 -j REDIRECT --to-port 8080
success
// 변경된 방화벽 규칙을 즉시 적용
$ firewall-cmd --reload
// 애플리케이션을 지정된 포트에서 백그라운드 실행
$ java -jar -Dserver.port=8080 pes-0.0.1-SNAPSHOT.jar &
테스트
서버 외부에서 telnet 명령어를 통해 80번 포트로 잘 연결되는지 확인한다. connected to IP가 나오면 성공적으로 연결되었다는 뜻이다.
$ telnet {IP} 80
Trying {IP}...
Connected to {IP}.
참조
Allowing a regular user to listen to a port below 1024
I need to allow a non-root user to run a server listening on port tcp/80. Is there any way to do this?
unix.stackexchange.com
'나의 에러 일지' 카테고리의 다른 글
Java - java.lang.UnsupportedClassVersionError 원인과 해결방법 (0) | 2023.11.09 |
---|---|
Eclipse MAT - An internal error occurred during: "Parsing heap dump" 원인과 해결 방법 (0) | 2023.10.27 |
Java - OutOfMemoryError:GC overhead limit exceeded 원인과 해결 방법 (Eclipse MAT) (0) | 2023.08.17 |
SSH - ssh no matching key exchange method found 에러 원인과 해결 방법 (0) | 2023.06.21 |
Spring - Login(Security) 요청에서 한글 깨짐 문제 원인과 해결 방법 (0) | 2023.06.15 |