필자가 맡고 있는 서비스에서 이슈가 발생했는데 어떤 이슈이고 어떻게 대응했는지 포스트로 남겨보려합니다.
말그대롭니다...컴퓨터에서는 서버와의 통신이 원활하게 이루어지지만 모바일기기(IOS) 에서는 오류가 내려오는 현상을 발견했습니다.
왜 그런걸까요?
서버와 모바일 기기간의 의사소통 문제로 발생한 이슈였습니다.
구글링을 해보니 초기 서버 설정 파일인 server.xml
에서 ciphers
와 같은 보완 설정이 적절히 구성되지 않았을 경우 발생 가능성이 있다고해서
한번 확인해보았습니다.
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<Server port="12005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="12000" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="12443" />
<Connector port="12443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="pathFile"
certificateKeystorePassword="Password"
type="RSA"
/>
</SSLHostConfig>
</Connector>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
주석을 제거 해도 뭐가 많다....하지만 우리가 주목해야할 부분은 바로 여기다.
<Connector port="12443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="pathFile"
certificateKeystorePassword="Password"
type="RSA"
/>
</SSLHostConfig>
</Connector>
위에서 서버와 클라이언트가 의사소통 문제라고 했었습니다.
조금 더 깊이 들어가 봅시다.
서버와 클라이언트 간에 사용되는 암호화 프로토콜 또는
ciphers
의 선택이 일치하지 않아 발생한 이슈였습니다.
즉, 서버와 클라이언트 간 암호화 프로토콜 또는 ciphers
가 호환이 되지않아 발생되었다는 말입니다.
그럼, 주목해야할 부분은 뭘까요?
바로 저 부분에 명시적으로 ciphers
를 지정해 모바일 기기와의 연결 안정성을 개선할 수 있습니다.
Cipher suite는 SSL(Secure Sockets Layer) 또는 TLS(Transport Layer Security) 프로토콜에서 데이터 암호화와 관련된 알고리즘과 키 교환 방식을 정의하는 문자열 집합입니다. 이는 서버와 클라이언트 간의 안전한 통신을 위해 사용되며, 암호화 알고리즘, 키 교환 방법, 메시지 인증 코드(MAC) 알고리즘, 그리고 선택적으로 의사 난수 생성기(Pseudo Random Function, PRF)를 포함합니다.
<Connector
port="12443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true">
<SSLHostConfig>
<Certificate
certificateKeystoreFile="pathFile"
certificateKeystorePassword="Password"
type="RSA" />
</SSLHostConfig>
</Connector>
<Connector
port="12443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="250"
maxHttpHeaderSize="8192"
emptySessionPath="true"
enableLookups="false"
acceptCount="100"
disableUploadTimeout="true"
SSLEnabled="true"
connectionTimeout="-1"
URIEncoding="UTF-8"
maxPostSize="-1"
keepAliveTimeout="-1"
maxParameterCount="-1"
scheme="https"
secure="true"
keystoreFile="pathFile"
keystorePass="Password"
ciphers="TLS_AES_128_GCM_SHA256,LS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
sslProtocol="TLS"
clientAuth="false">
</Connector>