개발 As 현생/오늘의 뻘짓 & 문제해결

웹소켓 커넥션에러 이유에 대한 고찰

민킹 2022. 2. 12. 22:20

 

-상황: SW설치 중 JAVA Client(CS 프로그램)에서 WAS로의 웹소켓 접속 불가

-에러: Connection timed out

-구조: 외부망 | DMZ(Web서버/JAVA Server 위치) | 내부망(WAS/DB/JAVA Client 위치)

          , 각 망은 요청받은 IP/Port를 제외하고 전부 차단 되어 있음

*JAVA Server역할 : 외부망에 위치한 교환기로 들어오는 전화데이터를 포멧화하여 데이터 제공

*JAVA Client역할 : JAVA Server로부터 데이터 수신(Socket 통신), 파싱 → WAS/DB로 데이터 전달

 

왜 Connection timed out?

해당 SW를 설치하며 'Connection timed out' 에러를 매우 많이 접했다. 이유는 매번 같았다. 접속하려는 주소가 방화벽에 의해 차단되어서. 방화벽에 막히는 이유는 두 가지였다.

 

첫째, 우리가 제출 한 네트워크 정책이 아직 반영되지 않았다.

둘째, 우리가 해당 IP/Port를 뚫어달라고 신청하지 않았다.

 

물론 커넥션 실패의 이유는 더 있겠지만 이번 프로젝트의 경우는 전부 방화벽이었다. 그렇기에 이번 웹소켓 접속 에러도 방화벽에 의해 차단되고 있다는 가정하에 원인 분석을 시도해 보았다.(우선 가능성이 제일 커 보이는 것 부터 시작해야 하니까)

 

네트워크 구성도와 정책을 찬찬히 다시 살펴 보았다.

 

 

.

.

.

'Key'가 될만한 조건은 대강 이러했다.

  • WEB(Apache) WAS(Tomcat) 분리
  • WEB서버 SSL 적용
  • 웹소켓은 IP가 아닌 도메인주소를 통해 EndPoint로 접속
  • AJP(WEB, WAS간의 통신용)와 HTTP(웹소켓용) 서로 다른 포트 사용
  • 웹소켓 작동을 위해 'VirtualHost'컨피그에 'ProxyPass'설정

 

WEB과 WAS가 분리되어 있기 때문에 별도의 설정 없이 웹소켓을 사용하는건 불가능하다. 그렇기에 WAS에 웹소켓(HTTP)통신을 위한 포트를 하나 더 열어준 것이다. 클라이언트의 URL요청(웹소켓 EndPoint로의 요청)을 이 포트로 우회 해주기 위해 VirtualHost컨피그 파일에 'ProxyPass'를 추가해 준 것이다.

 

웹소켓의 EndPoint 접속 주소가 잘못 되었나?

현장에서 당연히 될 줄 알았던 JAVA Client의 웹소켓 접속이 'Timed out'에러를 띄웠고...(지금은 해당 에러가 방화벽정책에 막혔기 때문이라는 추측이 가능하지만 당시에는 설치 초반이었기에 추측해내지 못했었다.)

뭐지? 주소가 잘못되었나? 하고 다시 확인해보지만 입력한 도메인주소는 토씨하나 틀리지 않고 정확했다.

wss://domain.com/webSocket.do (원래 정상작동 했어야 하는 URL)

 

그래 그럼 혹시모르니 해당 도메인의 IP주소로 직접 접속을 시도해보자(회사에서 테스트했을 때 되었던 기억이 떠오름).

wss://xxx.xxx.xxx.40/webSocket.do

네? 갑자기 404요? (이것도 뒤늦게 이유를 깨달았다. 알고싶다면 하단의 더보기 클릭)

더보기

SSL은 도메인에만 적용되어 있기 때문이다. 웹소켓은 ws/wss의 두 가지 접속 방법이 있고, 각각 HTTP/HTTPS로 볼 수 있다. 즉 'wss://xxx.xxx.xxx.40/webSocket.do'는 'https://xxx.xxx.xxx.40/webSocket.do'로의 접속시도인 것이다. 이 접속이 가능하려면  해당 IP를 도메인 주소로써 사용해야 한다. 하지만 우리가 구입한 SSL은 domain.com을 도메인주소로 쓰는 것이기에 IP주소 입력시 404를 띄우는 것이었다.(한마디로 존재하지 않는 도메인이니깐)

 

그럼 이건..?

ws://xxx.xxx.xxx.40/webSocket.do

SSL을 씌워놓았기 때문에 'Secure'한 요청이 아니면 안된다고 한다. 그래 안되겠지..

 

다시 첫번째로 돌아가 순서대로 재시도를 해보았다. 될리가 없다. 여기가 바로 무한루프 맛집인가요? 아냐.. 난 그런 맛집은 되고싶지 않아...

 

 

아니 그래서 wss://domain.com/webSocket.do 이놈 왜 안 된거지?

그러게말이다.. 같이 갔던 네트워크 엔지니어분은 RPC포트가 다 차단되어 있는 것 같다고 이건 어쩔 수 없다 하신다. 그리고 그 말을 들은 팀장님은 그럼 그냥 웹소켓 걷어내고 폴링방식으로 가자고 하신다. 하... 폴링 정말 싫은데... 어쨌든 일단 서비스는 해야하니 팀장님 말씀대로 폴링방식으로 변경을 해 놓고...(내 웹소켓 ㅠㅠ)

여러번의 막간을 이용해 나름대로의 원인 분석을 시도했고! 뭔가! 알아낸 것 같다!! 내가 생각하는 원인은.....

.

.

.

바로 DNS로의 Query실패이다!

  1. SSL때문에 무조건 도메인으로 접속해야 하는 상황
  2. 웹소켓 접속 에러를 내는 클라이언트는 딱 하나 JAVA Client
  3. JAVA Client는 내부망에 위치
  4. 사용 도메인의 DNS는 외부망에 위치
  5. 내부망 ↔ DNS를 위해 반영된 네트워크 정책 없음(당시 아무도 DNS 접속에 대해 생각하지 못했다)
  6. 심지어 내부망 ↔ 외부망 직접통신은 불가능(무조건 DMZ망을 통해야 함)

 

결론

DB사용때문에 JAVA Client를 내부망에 위치 시켰는데 해당 클라이언트를 DMZ로 빼고 DB관련 로직은 WAS에서 처리하게 변경해주면 될 것 같다.