๐ IBM JDK (WebSphere) ํ๊ฒฝ์์ HTTPS API ํธ์ถ ์ A system call received a parameter that is not valid ์๋ฌ ํธ๋ฌ๋ธ์ํ
๐ ๊ฒฐ๋ก ์์ฝ
1. ์๋ฌ๋ HTTP(APIํธ์ถ) ํ๋ผ๋ฏธํฐ๊ฐ ์ ํจํ์ง ์์๊ฒ ์๋๋ผ socket / protocol ์ํ์ด๋ค.
2. ์๋ฒ(WebSphere)์์ ์ธ๋ถ HTTPS๋ก ๋๊ฐ๋ Outbound TLS ํธ๋ํฝ์ด ์ฐจ๋จ๋จ.
→ ์ด๋ ๋คํธ์ํฌ/๋ณด์ ์ฅ๋น ์ ์ฑ ์์ญ์ผ๋ก ๋ณด์ํ์Outbound ํ์ฉ(SSL Inspection ์์ธ) ์์ฒญ์ด ํ์ํจ.
3. 2๋ฒ์ด ์๋๋ผ๋ฉด API์๋ฒ ์ธก legacy SSL ์ฌ์ฉ์ ์์ฌํ ์ ์๋ค.
๐ 1. ๋ฌธ์ ์ฆ์
Spring ๊ธฐ๋ฐ ๋ฐฐ์น์์ ์ธ๋ถ HTTPS API ํธ์ถ ์
- ๋ก์ปฌ PC(Windows)์์๋ ์ ์ ๋์
- ๊ฐ๋ฐ ์๋ฒ(WebSphere)์์ ์๋ ์ค๋ฅ ๋ฐ์
ERROR=org.springframework.web.client.ResourceAccessException:
I/O error on POST request for "https://api.example.com/api/apiurl":
A system call received a parameter that is not valid.;
nested exception is java.net.SocketException:
A system call received a parameter that is not valid.
HTTPS POST ์ SocketException ์ด๊ณ , ์๋ฌ ํฌ์ธํธ๋ Spring RestTemplate → SSL ์์ผ ์์ฑ ๋จ๊ณ.
ResourceAccessException
โโ java.net.SocketException
A system call received a parameter that is not valid
์ด ์๋ฌ๋ ์ ํ๋ฆฌ์ผ์ด์
๋ก์ง ๋ฌธ์ ๊ฐ ์๋๋ผ “JVM + OS + SSL ์ค์ ” ๋ฌธ์ ์ผ ํ๋ฅ ์ด ๋๋ค.
๐์๋ฌ ์ ํ ํ๋ฆ
[ํด๋ผ์ด์ธํธ ์๋ฒ]
TLS ClientHello ์ ์ก ์๋
↓
[๋คํธ์ํฌ/๋ณด์ ๊ณ์ธต]
์์๋ฐ์ด๋ TLS ์ฐจ๋จ ๋๋ RST
↓
[IBM JDK JSSE2]
์ ์์ ์ธ TLS ์๋ต ์์ ๋ถ๊ฐ
↓
[OS Socket Layer]
์์ผ write ์คํจ → invalid parameter
↓
[java.net.SocketException]
↓
[Spring ResourceAccessException]
๐ ์ฌ๊ธฐ์ ๋งํ๋ parameter๋
HTTP(APIํธ์ถ) ํ๋ผ๋ฏธํฐ๊ฐ ์๋๋ผ socket / protocol ์ํ
โ ์คํ ๋ฐฉ๋ฒ
*๋ก์ปฌ ์คํ (์ง์ ํฐ๋ฏธ๋์์)
java \
-Dapp.home=./config \
-cp "bin;lib/*" \
com.example.batch.MainApplication \
{MODE} {TARGET}
*์๋ฒ ์คํ (sh ์ผ๋ถ)
/path/to/java/bin/java \
-Dfile.encoding=UTF-8 \
-classpath ${CLASSPATH} ${JAVA_OPTIONS} \
-Xms256M -Xmx1024M \
com.example.batch.MainApplication \
${MODE} ${TARGET} \
> ${LOG_HOME}/batch_${TARGET}_${MODE}_$(date +%Y%m%d).log 2>&1 &
๐ 2. TLS(SSL)ํต์ ํ์ธ
๐ 2-1. ์๋ฒ(WebSphere) - openssl
*์ค๋๋ ์๋ฒ๋ผ curl ์ค์น ์ ๋์ด์์ (์๋ง CentOS).
AIX / IBM ์๋ฒ์๋ openssl์ด ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์.
โ openssl
openssl s_client๋ TLS(SSL) ํด๋ผ์ด์ธํธ ํ ์คํธ ๋๊ตฌ๋ก, HTTPS ํต์ ์์ HTTP๋ฅผ ์ ์ธํ TLS ๊ณ์ธต๊น์ง๋ง ๊ฒ์ฆํ๋ค.
๐์ฆ, Java(Spring RestTemplate)์ HTTPS ํต์ ์ค TLS Handshake ๋จ๊ณ๊น์ง๋ฅผ ๊ฑฐ์ ๊ทธ๋๋ก ์ฌํ.
โ๏ธ openssl ์ํํ๋ ๋จ๊ณ
- TCP 443 ์ฐ๊ฒฐ
- TLS ClientHello ์ ์ก
- ์๋ฒ์ Cipher Suite ํ์
- ์๋ฒ ์ธ์ฆ์ ์์
- ์ธ์ฆ์ ์ฒด์ธ ๊ฒ์ฆ
- TLS Handshake ์๋ฃ ์ฌ๋ถ ํ์ธ
* HTTP ์์ฒญ(GET/POST)์ ์ ์กํ์ง ์์ → TLS ๊ณ์ธต๋ง ๋จ๋ ์ผ๋ก ๊ฒ์ฆ
์คํ
$ openssl s_client -connect api.example.com:443 -tls1_2
๊ฒฐ๊ณผ
**๋ง์ฝ ๊ฒฐ๊ณผ๊ฐ ์๋์ ๋ค๋ฅด๋ค๋ฉด ๋ค๋ฅธ ์์ธ์ด๋ค. 3~5 ์ฐธ๊ณ !!
CONNECTED(00000003)
write:errno=73
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1765933594
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
ํด์
โ๏ธ CONNECTED
- TCP 443 ์ฐ๊ฒฐ ์ฑ๊ณต → ๋ฐฉํ๋ฒฝ / L4 ๋ฌธ์ x
โ write:errno=73
- ํด๋ผ์ด์ธํธ๊ฐ ClientHello๋ฅผ ๋ณด๋ด๋ ค๋ ์๊ฐ OS ๋ ๋ฒจ์์ write ์คํจ
- AIX ๊ธฐ์ค errno 73 = Protocol error / invalid argument ๊ณ์ด
- ๐ ์ฆ, TLS ๋ฐ์ดํฐ ์์ฒด๊ฐ ์๋์๊ฒ ์ ๋ฌ๋๊ธฐ ์ ์ ์ปค๋/๋ณด์ ๊ณ์ธต์์ ์ฐจ๋จ
โ no peer certificate
- ์๋ฒ๊ฐ ์๋ฌด๊ฒ๋ ์๋ต ์ ํจ
- ์ธ์ฆ์ ๋ฌธ์ โ (์์ง ๊ฑฐ๊ธฐ๊น์ง๋ ๋ชป ๊ฐ)
โ read/write 0 bytes
- TLS Handshake ์์์กฐ์ฐจ ์ ๋จ
- ์๋ ์๋ฒ๊ฐ ์ธ์ฆ์๋ฅผ ๋ณด๋ธ ๊ฒ ์๋๋ผ ์ฐ๋ฆฌ ์ชฝ์์ ํจํท์ ๋ชป ๋ด๋ณด๋
โ API ์ ๊ณต์ ๋ฌธ์ ์ผ ๊ฒฝ์ฐ
- ClientHello๋ ๋๊ฐ
- ServerHello / ์ธ์ฆ์ ์๋ต ์์
- handshake_failure / bad_certificate ๊ฐ์ ์๋ฌ ๋ฐ์
๐ ๊ฒฐ๋ก
์๋ฒ → ์ธ๋ถ ๋ฐฉํฅ(outbound) TLS ์ฐจ๋จ
์๋ฒ์์ ์ธ๋ถ HTTPS(API) ํธ์ถ ์, TCP 443 ์ฐ๊ฒฐ์ ์ ์์ด๋ TLS ClientHello ๋จ๊ณ์์
openssl s_client -tls1_2 ๊ธฐ์ค write errno=73 ๋ฐ์ํ๋ฉฐ ์๋ฒ๋ก๋ถํฐ SSL ์๋ต ์์ ๋์ง ์์.
์ ํ๋ฆฌ์ผ์ด์ (Java/Spring)๊ณผ ๋ฌด๊ดํ๊ฒ OS/๋ณด์/๋คํธ์ํฌ ๋ ๋ฒจ์์ ์์๋ฐ์ด๋ TLS๊ฐ ์ฐจ๋จ๋๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ฉฐ, ํด๋น ์๋ฒ → api.example.com:443 ๊ฒฝ๋ก์ ๋ํด SSL Inspection ๋๋ ๋ณด์ ์ ์ฑ ํ์ธ์ด ํ์ํ๋ค.
๐ 2-2. ๋ก์ปฌ - curl (์ ํด๋ ๋จ. ์๋ฒ์ ๋น๊ต)
โ curl
curl์ HTTPS ํด๋ผ์ด์ธํธ, HTTPS ํต์ (TLS ํ์) ํ์ธ
๐ Java(Spring RestTemplate)๊ฐ ํ๋ ๋์์ ๊ฑฐ์ ๊ทธ๋๋ก ์ฌํ
โ๏ธ curl ์ํํ๋ ๋จ๊ณ
- TCP 443 ์ฐ๊ฒฐ
- TLS ClientHello
- ์๋ฒ์ Cipher ํ์
- ์๋ฒ ์ธ์ฆ์ ์์
- ์ธ์ฆ์ ๊ฒ์ฆ
- HTTP ์์ฒญ ์ ์ก
์๋
curl -vk https://api.example.com/…
- -v : TLS Handshake ์์ธ ์ถ๋ ฅ
- -k : ์ธ์ฆ์ ๊ฒ์ฆ ๋ฌด์ (CA ๋ฌธ์ ๋ฐฐ์ ์ฉ)
๊ฒฐ๊ณผ
* Host api.example.com:443 was resolved.
* IPv6: (none)
* IPv4: 211.46.114.70
* Trying 111.11.111.11:443...
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server did not agree on a protocol. Uses default.
* Connected to api.example.com (111.11.111.11) port 443
* using HTTP/1.x
> GET /... HTTP/1.1
> Host: api.example.com
> User-Agent: curl/8.14.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 404 Not Found
< Server: nginx
< Date: Wed, 17 Dec 2025 01:23:13 GMT
< Content-Type: text/html
< Content-Length: 146
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
<
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host api.example.com left intact
ํด์
โ๏ธ DNS / ๋คํธ์ํฌ
* Connected to api.example.com (111.11.111.11) port 443
- DNS ์ ์, TCP 443 ์ ์ → ๋คํธ์ํฌ ๋ฌธ์ ์์
โ๏ธ TLS(SSL) ๊ณ์ธต (๊ฐ์ฅ ์ค์)
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server did not agree on a protocol. Uses default.
- schannel → Windows TLS ์คํ
- TLS handshake ์ ์ ์๋ฃ, ์๋ฒ๊ฐ ์ ์์ ์ผ๋ก ์๋ต ๐ TLS ํ์ ์ฑ๊ณต
- *ALPN์ ์ ํ ์ฌํญ → ๋ฌธ์ ์๋
โ๏ธ HTTP ๊ณ์ธต
> GET /... HTTP/1.1
< HTTP/1.1 404 Not Found
< Server: nginx
- โTLS ์คํจ์๋ค๋ฉด → ์ฌ๊ธฐ๊น์ง ๋ชป ์ด
- โ์ธ์ฆ์ ๋ฌธ์ ์๋ค๋ฉด → handshake ๋จ๊ณ์์ ์ปท
- โAPI ์๋ฒ ๋ฌธ์ ์๋ค๋ฉด → 5xx ๊ฐ๋ฅ์ฑ
- *404๋ URL ๊ฒฝ๋ก ๋ฌธ์ ์ผ ๋ฟ, ํต์ ์ฑ๊ณต์ ์ฆ๊ฑฐ์
- nginx๊ฐ ์์ฒญ์ “๋ฐ์์ ์ฒ๋ฆฌ”ํจ
๐ 3. (์ฐธ๊ณ ) API ์๋ฒ ์ธก ์๋ต ๋ฐ์๋ค๋ฉด ๊ฐ๋ฅํ ์๋๋ฆฌ์ค ์ ๋ฆฌ
โ ๏ธ ๋ณธ ํญ๋ชฉ์ ์ค์ ๋ฐ์ํ ์ํฉ์ด ์๋, ๊ฐ์ ์๋๋ฆฌ์ค ์ ๋ฆฌ์. ๋๋ 2๋ฒ์์ ํด๊ฒฐ๋์์ง๋ง ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ ๊ฐ์ ์๋ฌ๊ฐ ๋ ์ ์์ด์ ์ ๋ฆฌํจ.
โ 3-1. TLS ๋จ๊ณ์์ ๋ค๋ฅธ ์๋ต์ ๋ฐ์์ ๊ฒฝ์ฐ ๊ฐ๋ฅํ ํด์
openssl s_client -connect api.example.com:443 -tls1_2
๐น legacy SSL ์๋ต ์์ → API์๋ฒ ๋๋ ์๋จ SSL ์ฅ๋น์ legacy SSL ๊ตฌํ ๊ฐ๋ฅ์ฑ
CONNECTED(00000003)
SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
SSL alert number 40
๐น SSLv3 only / downgrade ์์ → API SSLv3 ๊ธฐ๋ฐ ์๋ต
CONNECTED(00000003)
wrong version number
๐น ServerHello๊น์ง๋ ๋๋ฌ, Java์์๋ง ์คํจ → IBM JDK์ SSL ์ ์ฑ /๊ตฌํ ์ฐจ์ด
CONNECTED(00000003)
depth=0 CN=*.lghnh.com
verify return:1
---
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE_RSA_AES_128_GCM_SHA256
๐4. JVM ์ต์ ์ ๊ฒ (๊ฐ๋ฅ์ฑ ๋ฐฐ์ ๋จ๊ณ)
โ ์๋ํ ์ต์ ๋ค
-Djava.net.preferIPv4Stack=true
-Dhttps.protocols=TLSv1.2
-Djdk.tls.client.protocols=TLSv1.2
๐ 4-1. -Djava.net.preferIPv4Stack=true
๋ชฉ์
- IPv6 / IPv4 ์ถฉ๋ ๊ฐ๋ฅ์ฑ ์ ๊ฑฐ
- JVM์ด ์์ผ ์์ฑ ์ IPv4๋ง ์ฌ์ฉํ๋๋ก ๊ฐ์
- ์๋ฒ๊ฐ IPv6 ์ฃผ์๋ฅผ ๋จผ์ ์ก๋๋ฐ ๋ฐฉํ๋ฒฝ / ๋คํธ์ํฌ๊ฐ IPv6์ ๋ง๊ณ ์์ ๋ ์ํจ
๊ฒฐ๊ณผ
- telnet์ผ๋ก TCP ์ฐ๊ฒฐ ์ ์ → DNS / IP ๋ฌธ์ ์์
- ์๋ฌ ๋ฐ์ ์ง์ ์ SSL Handshake ๋จ๊ณ
- โ ์ด๋ฒ ์ด์์ ๋ฌด๊ด
๐ 4-2. -Dhttps.protocols=TLSv1.2, -Djdk.tls.client.protocols=TLSv1.2
* -Dhttps.protocols๋ HTTPS ์ ์ฉ ์ต์ , -Djdk.tls.client.protocols๋ JDK JSSE ๋ ๋ฒจ ์ต์ ์ผ๋ก ์ ์ฉ ๋ฒ์๊ฐ ๋ค๋ฆ.
๋ชฉ์
- SSLv3 / TLS1.0 ์ฌ์ฉ ๋ฐฉ์ง TLSv1.2 ์ฌ์ฉ ๊ฐ์
- JVM์ด TLSv1.2๊ฐ ์๋ ํ๋กํ ์ฝ๋ก ํต์ ์ ์๋ํ๋์ง ์ฌ๋ถ ๊ฒ์ฆ
๊ฒฐ๊ณผ
CLIENT_DEFAULT: [TLSv1, TLSv1.1, TLSv1.2]
- JVM์ ์ด๋ฏธ TLSv1.2๋ก ํต์ ์๋ ์ค
- โ JVM ๋ฌธ์ ์๋
๐ 4-3. JVM ์ต์ ์ ๊ฒ ๊ฒฐ๋ก
| ๊ฐ๋ฅ์ฑ | ๊ฒฐ๊ณผ |
| IPv6 ์ถฉ๋ | โ ์๋ |
| JVM์ด SSLv3๋ก ํต์ ์๋ | โ ์๋ |
| TLS ๋ฒ์ ๋ฏธ์ง์ | โ ์๋ |
๐ JVM ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ธ ๋ฐฐ์ ์๋ฃ
๐ 5. SSL ๋๋ฒ๊ทธ ๋ก๊ทธ ๋ถ์
๋๋ฒ๊ทธ ์ต์ ์ถ๊ฐ
-Djavax.net.debug=ssl,handshake
์๋ฒ ๋ก๊ทธ
SSLv3 protocol was requested but was not enabled
IBMJSSE2 will not allow protocol SSLv3
*๋ก์ปฌ(Oracle JDK) ๋ก๊ทธ (์ฐธ๊ณ ์ฉ)
java -Djavax.net.debug=ssl,handshake -cp . apiReqSample > ssl_debug.log 2>&1 &
javax.net.ssl|DEBUG|30|main|2025-12-16 09:23:48.933 KST|SSLExtensions.java:272|Ignore, context unavailable extension: pre_shared_key
javax.net.ssl|DEBUG|30|main|2025-12-16 09:23:48.936 KST|ClientHello.java:638|Produced ClientHello handshake message (
"ClientHello": {
"client version" : "TLSv1.2",
//…
})
javax.net.ssl|DEBUG|30|main|2025-12-16 09:23:51.969 KST|ServerHello.java:877|Consuming ServerHello handshake message (
"ServerHello": {
"server version" : "TLSv1.2",
"random" : "{๋ฌธ์์ด}",
"session id" : "{๋ฌธ์์ด}",
"cipher suite" : "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F)",
"compression methods" : "00",
"extensions" : [
"renegotiation_info (65,281)": {
"renegotiated connection": [<no renegotiated connection>]
},
"server_name (0)": {
<empty extension_data field>
},
"ec_point_formats (11)": {
"formats": [uncompressed]
},
"extended_master_secret (23)": {
<empty>
}
]
}
)
๐ ๊ฒฐ๋ก
API ํธ์ถ์ IBM JDK(JSSE2) ํ๊ฒฝ์์ SSL handshake ๋จ๊ณ์์ ์คํจํ๋ฉฐ, ๋ก๊ทธ์ SSLv3 ๊ด๋ จ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋์ง๋ง ์ด๋ ์ค์ SSLv3 ์์ฒญ์ด ์๋๋ผ
IBMJSSE2์ ๋ณด์ ์ ์ฑ
์ ์ํด legacy SSL ํน์ฑ์ด ํฌํจ๋ handshake ํ๋ฆ์ด SSLv3 ๊ฒฝ๋ก๋ก ํ๋จ๋์ด ์ฐจ๋จ๋ ๋์์ด๋ค.
๋์ผ ์์ฒญ์ด Oracle JDK ํ๊ฒฝ์์๋ TLSv1.2๋ก ์ ์ ์ฒ๋ฆฌ๋๋ ์ ์์, ์๋ฒ ๋๋ ์ค๊ฐ SSL ์ฅ๋น์ legacy SSL ๊ตฌํ๊ณผ JDK๋ณ SSL ์คํ ์ฐจ์ด์ ๋ฐ๋ฅธ ํธํ์ฑ ๋ฌธ์ ๋ก ํ๋จํ ์ ์๋ค.
=> ์ด ๊ฒฝ์ฐ API ์๋ฒ ์ธก์์ TLSv1.2 ์ด์์ผ๋ก ํต์ ์ด ๊ฐ๋ฅํ๋๋ก SSL/TLS ์ค์ ์์ ์ด ํ์ํ๋ค.
๐ํ๊ฒฝ ๋น๊ต
โ Oracle JDK (๋ก์ปฌ)
- ClientHello: TLSv1.2
- ServerHello: TLSv1.2
- legacy SSL ์๋ต์ด ์์ด๋
→ TLSv1.2 ๊ฒฝ๋ก๋ก ์ ์ ํ์ ์งํ - ๋ด๋ถ์ ์ผ๋ก ํธํ์ฑ ์ฒ๋ฆฌ(fallback/์ฐํ)๊ฐ ํ์ฉ๋จ
โ IBM JDK (๊ฐ๋ฐ ์๋ฒ)
- SSL ๊ตฌํ์ฒด: IBMJSSE2
- legacy SSL ํน์ฑ์ด ๊ฐ์ง๋๋ handshake ํ๋ฆ ๋ฐ์ ์
→ SLv3 ๊ด๋ จ ๊ฒฝ๋ก๋ก ๋ถ๊ธฐ
→ ๋ณด์ ์ ์ฑ ์ ์ฆ์ ์ฐจ๋จ
- โ fallback / ์ฐํ ํ์ฉํ์ง ์์
๐์๋ฌ ์ ํ ํ๋ฆ
[API ์๋ฒ]
SSL handshake ๊ณผ์ ์์ legacy SSL ๊ตฌํ ๊ธฐ๋ฐ ์๋ต ์ ๋ฌ
↓
[IBM JDK SSL ์์ง (JSSE2)]
SSLv3 ๊ด๋ จ protocol ๊ฒฝ๋ก๋ก ๋ถ๊ธฐ ์๋
→ ๋ณด์ ์ ์ฑ
์ ํด๋น ๊ฒฝ๋ก ์ฆ์ ์ฐจ๋จ
↓
[JSSE]
SSL handshake ์ค๋จ
↓
[OS socket layer]
์์ผ ์ด๊ธฐํ ์คํจ → "invalid parameter" ๋ฐํ
↓
[java.net.SocketException]
↓
[Spring ResourceAccessException]