SOAP API の連携開発で突然 「Connection Timed Out」 や 「Connection Refused」 というエラーが発生すると、原因の特定に苦労します。ネットワーク層の問題なのか、SOAP サービス側の問題なのか、あるいはクライアントの設定ミスなのか。この記事では、これらのエラーの原因をレイヤーごとに分析し、体系的な対処法を解説します。
Connection Refused と Connection Timed Out の違い
まず、この 2 つのエラーは根本的に異なります。
Connection Refused(接続拒否): サーバーに到達できたが、指定ポートでサービスが待ち受けていない。TCP レベルで即座に RST パケットが返される。
Connection Timed Out(接続タイムアウト): サーバーに到達できず、TCP 接続の確立がタイムアウトした。ファイアウォールでパケットが遮断されている可能性が高い。
# Connection Refused の例
$ curl https://example.com:8443/service?wsdl
curl: (7) Failed to connect to example.com port 8443: Connection refused
# Connection Timed Out の例
$ curl --connect-timeout 10 https://example.com/service?wsdl
curl: (28) Connection timed out after 10001 milliseconds
原因 1: ファイアウォールとネットワーク制限
企業の SOAP サービスは多くの場合、IP ホワイトリストやファイアウォールルールで保護されています。自社の IP アドレスがアクセス許可リストに含まれていない場合、Connection Timed Out になります。
確認方法:
# サーバーのポートに到達できるか確認
nc -zv example.com 443 -w 5
# 成功例: Connection to example.com 443 port [tcp/https] succeeded!
# 失敗例: nc: connectx to example.com port 443 (tcp) failed: Operation timed out
# 自分のグローバル IP を確認
curl https://ifconfig.me
# traceroute でパケットの経路を確認
traceroute example.com
対処法: サービスプロバイダーにグローバル IP アドレスのホワイトリスト登録を依頼してください。クラウド環境の場合、NAT ゲートウェイや Elastic IP の固定 IP を使用する必要があります。
原因 2: プロキシ設定の問題
企業ネットワークではインターネットアクセスにプロキシサーバーを経由することが一般的です。SOAP クライアントがプロキシを経由していない場合、外部のサービスに到達できません。
// Node.js: node-soap でプロキシを設定
const soap = require('soap');
const HttpsProxyAgent = require('https-proxy-agent');
const agent = new HttpsProxyAgent('http://proxy.corp.example.com:8080');
const client = await soap.createClientAsync(wsdlUrl, {
request: require('axios').create({
httpsAgent: agent,
proxy: false // axios 独自のプロキシ設定を無効化
})
});
# Python: zeep でプロキシを設定
from zeep import Client
from zeep.transports import Transport
from requests import Session
session = Session()
session.proxies = {
'http': 'http://proxy.corp.example.com:8080',
'https': 'http://proxy.corp.example.com:8080'
}
transport = Transport(session=session)
client = Client(wsdl_url, transport=transport)
# curl でプロキシ経由の確認
curl -x http://proxy.corp.example.com:8080 https://example.com/service?wsdl
対処法: ネットワーク管理者にプロキシサーバーのアドレスを確認し、SOAP クライアントに正しく設定してください。
原因 3: SSL/TLS の問題
SOAP サービスが古い TLS バージョン(TLS 1.0/1.1)のみをサポートしている場合や、自己署名証明書を使用している場合、接続に失敗します。
# サーバーの TLS バージョンを確認
openssl s_client -connect example.com:443 -tls1_2
# 証明書の詳細を確認
openssl s_client -connect example.com:443 -showcerts 2>/dev/null | \
openssl x509 -noout -dates -subject
// Node.js: 自己署名証明書を一時的に許可(開発環境のみ)
const https = require('https');
const agent = new https.Agent({
rejectUnauthorized: false // 本番環境では絶対に使わない
});
const client = await soap.createClientAsync(wsdlUrl, {
request: require('axios').create({ httpsAgent: agent })
});
対処法: サーバーが古い TLS のみ対応の場合はプロバイダーに更新を要請してください。自己署名証明書の場合は、その CA 証明書をクライアントの信頼ストアに追加してください。
原因 4: サービスのエンドポイント URL の間違い
WSDL に記載されたエンドポイント URL と実際のサービス URL が異なるケースがあります。特に、WSDL が内部ネットワーク用の URL(http://localhost:8080/service など)を含んでいる場合に問題が発生します。
<!-- WSDL 内のサービス定義を確認 -->
<wsdl:service name="UserService">
<wsdl:port name="UserPort" binding="tns:UserBinding">
<!-- この URL が正しいか確認 -->
<soap:address location="http://internal-server:8080/UserService"/>
</wsdl:port>
</wsdl:service>
対処法: WSDL を取得した URL とエンドポイントが一致しているか確認してください。多くの SOAP クライアントライブラリでは、エンドポイント URL を上書きできます。
// node-soap: エンドポイントを上書き
client.setEndpoint('https://actual-server.example.com/UserService');
原因 5: タイムアウト値の設定不足
SOAP サービスは処理に時間がかかることがあります。特に、大量のデータを返すオペレーションや、バックエンドで複数のシステムを呼び出す処理では、デフォルトのタイムアウト値(多くの場合 30 秒)を超えることがあります。
// Node.js: タイムアウト値の設定
const client = await soap.createClientAsync(wsdlUrl, {
request: require('axios').create({
timeout: 120000 // 120 秒
})
});
# Python: zeep でタイムアウトを設定
from zeep import Client
from zeep.transports import Transport
transport = Transport(timeout=120, operation_timeout=120)
client = Client(wsdl_url, transport=transport)
// Java: JAX-WS でタイムアウトを設定
BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put("com.sun.xml.ws.connect.timeout", 120000);
bp.getRequestContext().put("com.sun.xml.ws.request.timeout", 120000);
体系的なデバッグ手順
接続エラーに遭遇したら、レイヤーの下から順に確認していくのが効率的です。
- DNS 解決:
nslookupまたはdigでホスト名が正しく解決されるか確認する。 - TCP 接続:
nc -zvでポートに到達できるか確認する。 - TLS ハンドシェイク:
openssl s_clientで証明書と TLS バージョンを確認する。 - HTTP レイヤー:
curl -vで HTTP リクエストとレスポンスの詳細を確認する。 - SOAP レイヤー: 上記がすべて成功したら、SOAP エンベロープの内容を確認する。
# 上記をまとめて確認するワンライナー
curl -v --connect-timeout 10 -H "Content-Type: text/xml" \
"https://example.com/service?wsdl" 2>&1 | head -30
ネットワーク問題を回避する構成
SOAP サービスとの接続で頻繁にネットワーク問題が発生する場合、クライアントとサービスの間にプロキシ層を設けることで安定性を向上できます。SOAPless は SOAP サービスへの接続を一元管理し、リトライ処理やタイムアウト制御を自動で行います。クライアント側は SOAPless の REST エンドポイントに JSON を送るだけなので、ネットワーク設定の複雑さから解放されます。WSDL の URL を入力すれば約 30 秒で利用を開始でき、SOAP 特有の接続問題の多くを SOAPless 側で吸収できます。