#WebSphere

[WebSphere] 실제 IP(Real IP) 인식 불가 해결: trustedHeaderOrigin 설정 가이드 (CVE-2012-5783 대응)

WebSphere Application Server(WAS)의 trustedHeaderOrigin 설정이 개선되었습니다. 기존에는 정확한 IP만 입력해야 했으나, 최신 픽스팩(9.0.5.7, 8.5.5.20)부터는 192.168.*.*와 같은 IP 세그먼트 와일드카드를 지원합니다. 유동 IP 환경에서의 설정법과 적용 버전을 정리합니다.

1. 업데이트 배경: IP 관리가 너무 힘들다?

기존에는 보안(CVE-2012-5783) 이슈로 인해 trustedHeaderOrigin에 앞단 웹 서버의 정확한 IP(Full IP)를 일일이 등록해야 했습니다.

하지만 클라우드(AWS, Azure)나 컨테이너(Docker/K8s) 환경에서는 L4/Web 서버의 IP가 수시로 변경되거나 대역으로 할당되므로, 모든 IP를 나열하는 것이 불가능했습니다. 이를 해결하기 위해 부분 와일드카드(IP Wildcard Segments) 지원이 추가되었습니다.


2. 와일드카드 지원 버전 (Target Fixpacks)

아래 버전 이상의 픽스팩(Fix Pack)이 적용된 환경에서는 IP 대역 설정이 가능합니다.

제품군 지원 시작 버전 (Minimum Version)
WAS 9.0 9.0.5.7 이상
WAS 8.5 8.5.5.20 이상
Liberty 21.0.0.2 이상
참고: 위 버전보다 낮은 경우 192.168.*.* 같은 입력을 인식하지 못하고 에러가 발생하거나 IP 인식이 실패할 수 있습니다.

3. 설정 가이드 (Configuration)

WAS 관리 콘솔에서 전송 채널의 사용자 정의 속성을 추가합니다.

설정 경로

  1. Servers > [서버명] > Web Container Settings > Web container transport chains
  2. 대상 체인 선택 (예: WCInboundDefault)
  3. HTTP Inbound Channel (HTTP_2) > Custom properties > New

속성 값 입력 예시 (New Feature)

이제 아래와 같이 유연한 설정이 가능합니다.

속성 이름 (Name) 값 (Value) 예시 설명
trustedHeaderOrigin

trustedSensitiveHeaderOrigin
10.10.*.* 10.10.0.0/16 대역의 모든 IP 신뢰 (추천)
192.168.1.*, 10.1.*.* 콤마(,)를 사용하여 여러 대역 동시 지정
*.ibm.com 호스트네임 기반의 와일드카드 지원
Best Practice:
과거에는 편의상 * (전체 허용)를 사용하는 경우가 많았으나, 이는 보안상 취약합니다.
이제는 10.10.*.* 처럼 내부망 IP 대역만 특정하여 허용함으로써 보안과 편의성을 모두 챙길 수 있습니다.

4. 웹 컨테이너 포트 인식 설정 (함께 적용)

IP 대역 설정과 함께, 호스트 헤더의 포트 정보를 올바르게 가져오기 위한 웹 컨테이너 설정도 잊지 마세요.

  • 위치: Web Container > Custom properties
  • 속성: com.ibm.ws.webcontainer.extractHostHeaderPort = true

5. 검증 (Verification)

  1. 설정 저장 후 WAS 재기동
  2. SystemOut.log에 별다른 에러 메시지가 없는지 확인
  3. 애플리케이션에서 request.getRemoteAddr() 호출 시 실제 클라이언트 IP가 출력되는지 확인
Open Stream →
#IBM HTTPServer

[IHS/WAS] 실제 클라이언트 IP(Real IP) 식별 가이드: mod_remoteip 설정 및 버전별 패치 현황 (9.0.5.13)

로드밸런서(L4/L7) 환경에서 실제 클라이언트 IP를 식별하기 위해 IBM HTTP Server(IHS) 9.0의 mod_remoteip를 설정하는 방법을 다룹니다. 특히 보안 감사 로그의 무결성을 위해 IHS 9.0.5.13 (APAR PH47286) 패치가 왜 중요한지, 그리고 버전별 로그 포맷 설정 차이점을 중점적으로 정리합니다.

0. 배경: 왜 IP가 바뀔까?

클라이언트가 로드밸런서(Proxy)를 거쳐 웹 서버에 접속하면, 웹 서버 입장에서는 연결을 요청한 주체가 로드밸런서이므로 Source IP가 로드밸런서 IP(예: 10.0.0.1)로 기록됩니다.

이는 다음과 같은 보안 문제를 야기합니다.

  • 접근 제어 실패: IP 기반의 ACL(Access Control List) 적용 불가
  • 감사 추적 불가: 사고 발생 시 실제 공격자의 IP를 로그에서 찾을 수 없음

1. 버전별 패치 및 로그 포맷 주의사항 (Version History)

IHS 설정에 앞서, 사용 중인 IHS 버전에 따라 로그 포맷 변수를 다르게 써야 하므로 버전 확인이 필수적입니다.

📢 핵심 패치 정보: APAR PH47286

적용 버전: IBM HTTP Server 9.0.5.13 이상

내용: 이전 버전에서는 mod_remoteip가 정상 작동해도, 기본 로그 변수인 %h가 여전히 프록시 IP를 출력하는 문제가 있었습니다. 9.0.5.13부터는 %hmod_remoteip에 의해 변경된 실제 IP를 반영하도록 수정되었습니다.

버전별 권장 로그 포맷

IHS 버전 Access Log 권장 변수 설명
9.0.5.12 이하 %a (Client IP) %h는 프록시 IP를 찍으므로 사용 금지. 반드시 %a 사용.
9.0.5.13 이상 %h 또는 %a 패치 적용됨. %h를 써도 실제 IP가 기록됨 (기존 설정 유지 가능).

2. IHS 설정 가이드 (httpd.conf)

Step 1: 모듈 활성화

# mod_remoteip 모듈 주석 해제
LoadModule remoteip_module modules/mod_remoteip.so

Step 2: 신뢰할 프록시 등록

보안을 위해 "누가 보내준 헤더를 믿을 것인가"를 명시해야 합니다. 아무 헤더나 믿으면 IP 스푸핑 공격에 당할 수 있습니다.

<IfModule mod_remoteip.c>
    # 1. 실제 IP가 담긴 헤더명 지정 (표준: X-Forwarded-For)
    RemoteIPHeader X-Forwarded-For

    # 2. 신뢰할 로드밸런서(L4/L7) IP 등록
    # 사설 IP 대역의 프록시인 경우 (10.x, 192.168.x 등)
    RemoteIPInternalProxy 10.0.0.1 10.0.0.2

    # 공인 IP 대역의 프록시인 경우
    # RemoteIPTrustedProxy 203.0.113.5
</IfModule>

Step 3: 로그 포맷 변경 (Access Log)

버전에 관계없이 가장 안전한 방법은 %a 변수를 사용하는 것입니다.

# [기존] common 포맷 (9.0.5.12 이하에서 문제 발생 가능)
# LogFormat "%h %l %u %t \"%r\" %>s %b" common

# [변경] %h -> %a 로 변경 (권장)
LogFormat "%a %l %u %t \"%r\" %>s %b" common

3. 검증 및 디버깅 (Validation)

설정 적용 후 실제로 헤더가 잘 변환되는지 확인하기 위해 임시로 로그를 상세하게 찍어봅니다.

# 디버깅용 로그 포맷 정의 (작업 후 주석 처리 권장)
# %{c}a : Connection IP (L4 IP)
# %a    : Client IP (변환된 실제 IP)
GlobalLog logs/remoteip_debug.log "L4-IP=%{c}a Real-IP=%a XFF-Header=%{X-Forwarded-For}i"

정상 결과 예시:

L4-IP=10.0.0.1 Real-IP=203.0.113.2 XFF-Header=203.0.113.2
  • L4-IP에는 로드밸런서 IP가 나와야 함
  • Real-IP에는 실제 사용자 PC의 IP가 나와야 함 (성공)

4. WAS(WebSphere) 추가 설정 필요 여부

IHS에서 mod_remoteip가 정상 작동하면, WAS 플러그인(Plugin)으로 넘어갈 때 이미 Source IP가 복원된 상태로 넘어갑니다. 따라서 WAS 쪽에서는 별도의 추가 설정 없이 request.getRemoteAddr() 호출 시 실제 IP를 획득할 수 있습니다.

(단, Plugin 설정의 TrustedProxyEnable 속성은 상황에 따라 검토가 필요할 수 있습니다.)

Open Stream →
#Liberty

[WebSphere Liberty] DB 연결 총정리: Oracle, DB2, MySQL, Tibero 데이터소스 설정 및 연결 테스트

IBM WebSphere Liberty에서 주요 데이터베이스(Oracle, DB2, MySQL, Tibero)와 연결하기 위한 JDBC 데이터소스 설정 방법을 정리합니다. adminCenter를 활용한 관리 환경 구성, 비밀번호 암호화, 그리고 restConnector를 이용한 연결 테스트까지의 전체 과정을 다룹니다.

0. 전제 조건 (Prerequisites)

  • Version: Liberty 25.x 이상 권장
  • Java: Java 8 (OpenJ9) 기준
  • 필수 기능(Feature): server.xml에 아래 피처들이 등록되어 있어야 합니다.
<featureManager>
    <feature>jdbc-4.3</feature>              <!-- JDBC 표준 지원 -->
    <feature>transportSecurity-1.0</feature> <!-- 암호화 비밀번호 사용 시 -->
    <feature>restConnector-2.0</feature>     <!-- 연결 테스트 API용 -->
    <feature>adminCenter-1.0</feature>       <!-- 관리 UI 및 통합 관리 -->
</featureManager>

1. JDBC 드라이버 준비 (Driver Setup)

각 DB 벤더에 맞는 JDBC 드라이버(JAR 파일)를 준비하여 Liberty 공용 리소스 디렉토리에 배치합니다.

DB 파일명 (예시) 다운로드 출처
Oracle ojdbc8.jar Oracle MOS 또는 Maven
DB2 db2jcc4.jar DB 서버의 /sqllib/java
MySQL mysql-connector-j-8.x.jar Maven Central
Tibero tibero6-jdbc.jar TmaxSoft 테크넷

디렉토리 생성 및 복사

관리 편의성을 위해 ${shared.resource.dir}(기본값: usr/shared/resources) 하위에 벤더별 폴더를 만들어 관리하는 것을 추천합니다.

# Oracle 예시
mkdir -p $WLP_HOME/usr/shared/resources/jdbc/oracle
cp ojdbc8.jar $WLP_HOME/usr/shared/resources/jdbc/oracle/

2. 공통 라이브러리 정의 (Library)

server.xml에서 위에서 배치한 JAR 파일을 참조하는 library 태그를 작성합니다.

<!-- Oracle 라이브러리 정의 -->
<library id="OracleLib">
    <fileset dir="${shared.resource.dir}/jdbc/oracle" includes="ojdbc*.jar"/>
</library>

3. 데이터소스 정의 (DataSource Configuration)

DB별로 설정 태그(properties)와 클래스명이 다르므로 주의해야 합니다.

Case A: Oracle Database

<dataSource id="OracleDS" jndiName="jdbc/oracleDS" statementCacheSize="60">
    <jdbcDriver libraryRef="OracleLib"
                javax.sql.ConnectionPoolDataSource="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
    <!-- URL 방식 연결 -->
    <properties.oracle URL="jdbc:oracle:thin:@//192.168.0.101:1521/ORCL"
                       user="scott" password="{aes}..." />
    <connectionManager maxPoolSize="50" connectionTimeout="6s"
                       reapTime="300" maxIdleTime="1800"/>
</dataSource>

Case B: IBM DB2

<dataSource id="DB2DS" jndiName="jdbc/db2" isolationLevel="TRANSACTION_READ_COMMITTED">
    <jdbcDriver libraryRef="DB2Lib"
                javax.sql.ConnectionPoolDataSource="com.ibm.db2.jcc.DB2ConnectionPoolDataSource"/>
    <properties.db2.jcc databaseName="SAMPLE" serverName="localhost" portNumber="50000"
                        user="db2inst1" password="{aes}..." />
</dataSource>

Case C: Tibero (Tmax)

국산 DB인 Tibero는 properties 태그가 별도로 없으므로 일반적인 속성 주입 방식을 사용하거나, Tibero 전용 프로퍼티를 명시해야 할 수 있습니다.

<dataSource id="TiberoDS" jndiName="jdbc/tibero" statementCacheSize="100">
    <jdbcDriver libraryRef="TiberoLib"
                javax.sql.ConnectionPoolDataSource="com.tmax.tibero.jdbc.ext.TbConnectionPoolDataSource"/>
    <!-- properties.tibero 태그 사용 -->
    <properties.tibero url="jdbc:tibero:thin:@192.168.0.111:8629:tibero"
                       user="admin" password="{aes}..." />
</dataSource>

4. 비밀번호 암호화 (Security)

설정 파일에 비밀번호를 평문으로 저장하는 것은 보안상 위험합니다. securityUtility를 이용해 AES로 암호화합니다.

암호화 실행

# 암호화 키 지정 (예: passw0rd)
$WLP_HOME/bin/securityUtility encode --encoding=aes --key=passw0rd 'DB_REAL_PASSWORD'
# 결과: {aes}AA6wcy4K2Xm...

키 등록 (bootstrap.properties)

서버가 암호를 복호화할 수 있도록 키를 등록해줍니다.

wlp.password.encryption.key=passw0rd

5. 연결 테스트 및 검증 (Validation)

서버를 기동한 후, REST API를 통해 데이터소스 연결 상태를 체크할 수 있습니다.

필수 확인 (Check Point):
해당 API를 호출하거나 웹 관리 콘솔(Admin Center)을 이용하기 위해서는 adminCenter-1.0restConnector-2.0 피처가 반드시 활성화되어 있어야 하며, 접근하는 계정에 관리자(Administrator) 권한이 있어야 합니다.

연결 테스트 명령어 (curl)

# 관리자 계정(admin)으로 인증 후 테스트 API 호출
curl -k -u admin:passw0rd \
  https://localhost:9443/ibm/api/validation/dataSource/OracleDS

성공 시: 200 OK와 함께 JSON 응답 내에 "Valid" 메시지가 포함됩니다.
실패 시: messages.log 파일에서 CWLLG2010E(로드 실패), CWNEN0034E(연결 실패) 등의 에러 코드를 확인합니다.


6. 트러블슈팅 체크리스트

  • ClassNotFoundException: library 경로 오타 또는 JAR 파일 권한(755) 확인
  • Connection Timeout: DB 방화벽(Port) 오픈 여부 확인
  • Authentication Failed: bootstrap.properties에 암호화 키가 올바르게 등록되었는지 확인
Open Stream →
#Liberty

[WebSphere Liberty] 설정 유연화의 핵심: 변수(Variable) 활용법 및 우선순위 완벽 정리

WebSphere Liberty의 설정 파일(server.xml)에서 포트 번호, DB 접속 정보 등을 하드코딩하지 않고 변수(Variable)로 관리하는 방법을 정리합니다. bootstrap.propertiesserver.xml, 환경 변수 간의 우선순위 규칙과 JDBC URL 설정 시 발생하는 슬래시(/) 정규화 문제를 해결하는 팁을 다룹니다.

0. 변수를 왜 사용해야 하나요?

서버 설정을 변수화하면 하나의 server.xml 파일을 여러 서버 인스턴스나 환경(Dev/Test/Prod)에서 공유할 수 있습니다. 변경되는 값(포트, IP 등)만 별도로 분리하여 관리 효율성을 높일 수 있습니다.


1. 변수 정의 위치 및 우선순위 (Precedence)

Liberty에서 변수를 정의할 수 있는 곳은 크게 세 군데입니다. 만약 같은 이름의 변수가 여러 곳에 정의되어 있다면, 아래 순서대로 덮어씌워집니다. (아래쪽이 우선순위 높음)

  1. 프로세스 환경 변수 (OS Environment Variables): 가장 낮은 우선순위
  2. bootstrap.properties: 환경 변수를 덮어씀
  3. server.xml (또는 include 된 xml): 가장 높은 우선순위 (최종 승자)
Best Practice:
서버별로 달라지는 고유 설정(예: HTTP 포트)은 bootstrap.properties에 정의하고, 여러 서버가 공유하는 공통 설정(예: DB 설정)은 included xml 파일에 정의하는 것이 좋습니다.

2. 변수 사용 방법 (Usage Guide)

Case A: bootstrap.properties 활용

서버 인스턴스 생성 시 자동으로 만들어지는 파일로, key=value 형태로 간단하게 정의합니다.

# bootstrap.properties
# 포트 번호 정의
http.port=8080
https.port=9443

Case B: server.xml 활용

<variable> 태그를 사용하여 정의하거나, 정의된 변수를 ${...} 문법으로 사용합니다.

<!-- 변수 정의 (Global) -->
<variable name="http.port" value="8080" />

<!-- 변수 사용 -->
<httpEndpoint id="defaultHttpEndpoint"
              httpPort="${http.port}"
              httpsPort="${https.port}" />

Case C: 환경 변수(Environment Variable) 활용

OS 환경 변수를 가져올 때는 env. 접두사를 사용합니다.

<!-- OS의 LIBRARY_DIR 환경 변수 사용 -->
<fileset dir="${env.LIBRARY_DIR}" includes="*.jar"/>

3. 고급 활용 팁 (Advanced Tips)

1) JDBC URL 슬래시(/) 정규화 문제 해결

Liberty 설정 파서(Parser)는 변수 값에 포함된 연속된 슬래시(//)를 단일 슬래시(/)로 정규화하는 특성이 있습니다. 이 때문에 JDBC URL 등이 깨질 수 있습니다.

해결책: 값을 두 부분으로 나누어 정의하거나, 이중 슬래시로 시작하게 합니다.

# [Bad] 이렇게 하면 jdbc:db2:/host.com 으로 변환되어 에러 발생
# DB_URL="jdbc:db2://host.com"

# [Good] 두 부분으로 나누어 결합
URL_PART_1="jdbc:db2:"
URL_PART_2="//host.com"
<dataSource ...>
    <properties.db2.jcc url="${URL_PART_1}${URL_PART_2}" />
</dataSource>

2) 리스트(List) 변수 처리

콤마(,)로 구분된 값을 단순 문자열이 아닌 리스트로 인식시키려면 ${list(...)} 함수를 사용합니다.

<variable name="ports" value="80,9080"/>

<!-- 문자열 "80, 9080"으로 인식 -->
<myConfig value="${ports}" /> 

<!-- 리스트 ["80", "9080"]으로 인식 -->
<myConfig value="${list(ports)}" />

3) 산술 연산 (Arithmetic)

포트 오프셋 등을 설정할 때 간단한 사칙연산(+, -, *, /)이 가능합니다.

<!-- 기본 포트(8080)에 1을 더해 8081로 설정 -->
<httpEndpoint id="secondaryEndpoint" httpPort="${http.port+1}" />

4. 변수 명명 규칙 (Naming Convention)

변수 이름은 반드시 알파벳(문자)으로 시작해야 하며, 아래 문자들만 포함할 수 있습니다.

  • 알파벳 문자 (Alphabetic characters)
  • 숫자 (Numeric characters)
  • 언더스코어 (_)
  • 점 (.)

Next Step:
이제 server.xml에서 하드코딩된 값을 제거하고 bootstrap.properties로 옮겨보십시오. 이를 통해 Docker 이미지 빌드나 여러 환경 배포 시 설정 관리가 훨씬 수월해질 것입니다.

Open Stream →
#Liberty

[WebSphere] Liberty Performance Tuning: 주요 구성 매개변수 가이드

Summary: WebSphere Liberty(Open Liberty) 환경에서 성능 최적화를 위해 조정 가능한 주요 매개변수를 정리한 문서입니다. JVM 힙 설정부터 Connection Pool, Executor, 그리고 유휴 자원 관리까지 server.xmljvm.options를 통한 튜닝 포인트를 다룹니다.

WebSphere Liberty는 기본적으로 자가 튜닝(Self-tuning) 기능을 갖추고 있으나, 운영 환경의 특성이나 애플리케이션의 워크로드 패턴에 따라 명시적인 설정 변경이 필요할 수 있습니다. 본 문서는 IBM Documentation을 기반으로 성능에 직접적인 영향을 주는 핵심 속성들을 정리했습니다.

1. JVM Tuning

가장 기본적이며 중요한 단계입니다. ${server.config.dir}/jvm.options 파일을 사용하여 설정합니다.

  • 개발 환경: 빠른 서버 시작을 위해 최소 힙(Min Heap)은 작게, 최대 힙(Max Heap)은 필요한 만큼 설정.
  • 운영 환경: 런타임 중 힙 크기 조정(Expansion/Contraction)에 따른 오버헤드를 제거하기 위해 최소 힙과 최대 힙을 동일한 값으로 설정하는 것을 권장합니다.

2. Transport Channel Service Tuning

클라이언트 연결, HTTP I/O 처리, 스레드 풀 및 연결 풀 관리를 담당하는 영역입니다. server.xml에서 설정합니다.

HTTP Options

SSL 핸드셰이크 비용이 높거나 처리량이 중요한 애플리케이션의 경우 지속적 연결(Persistent Connection) 설정을 최적화해야 합니다.

  • maxKeepAliveRequests: 단일 HTTP 연결에서 허용되는 최대 요청 수입니다. -1로 설정 시 무제한을 의미하며, 연결 맺는 비용을 절감할 수 있습니다.
<httpOptions maxKeepAliveRequests="-1" />

Connection Manager

데이터베이스 연결 풀(Connection Pool) 성능을 결정짓는 핵심 속성입니다.

  • maxPoolSize: 최대 실제 연결 수 (Default: 50). 모든 스레드가 DB 연결을 필요로 한다면 coreThreads와 1:1 매핑을 고려하십시오.
  • purgePolicy: Stale Connection 발견 시 처리 정책. 기본값은 EntirePool이나, FailingConnectionOnly로 설정하여 실패한 연결만 제거하는 것이 효율적입니다.
  • numConnectionsPerThreadLocal: 실행 스레드별로 DB 연결을 캐싱하여 락 경합(Contention)을 줄입니다. 멀티 코어 시스템에서 성능 향상에 유리합니다.
<connectionManager id="defaultConnectionManager" 
                   maxPoolSize="40" 
                   purgePolicy="FailingConnectionOnly" 
                   numConnectionsPerThreadLocal="1" />

Note: numConnectionsPerThreadLocal 사용 시, maxPoolSize는 (애플리케이션 스레드 수 × 스레드당 연결 수) 이상으로 설정해야 합니다.

3. Data Source Optimization

DB 쿼리 성능 및 데이터 무결성 수준을 조정합니다.

Statement Cache

PreparedStatement 캐싱을 통해 파싱 비용을 줄입니다. 애플리케이션에서 사용하는 고유한 SQL 문장 수보다 크게 설정해야 합니다.

<dataSource ... statementCacheSize="60" > ... </dataSource>

Isolation Level

데이터 무결성과 동시성(Concurrency)은 트레이드오프 관계입니다. isolationLevel 속성으로 조정합니다.

  • TRANSACTION_READ_UNCOMMITTED: 성능 최상, 무결성 최저 (Dirty Read 발생).
  • TRANSACTION_READ_COMMITTED: Dirty Read 방지.
  • TRANSACTION_REPEATABLE_READ: Dirty/Non-repeatable Read 방지.
  • TRANSACTION_SERIALIZABLE: 성능 최저, 무결성 최상 (완전한 직렬화).

4. Executor (Thread Pool) Tuning

Liberty의 Executor는 워크로드에 따라 스레드를 동적으로 조절하는 자가 튜닝 로직을 가지고 있습니다.

  • 기본 원칙: 특별한 문제가 없다면 설정을 변경하지 않는 것이 권장됩니다.
  • 예외 상황: 교착 상태(Deadlock) 해결 로직이 과도하게 작동하거나, 시스템 자원 한계로 스레드 수를 제한해야 할 경우 coreThreadsmaxThreads를 명시합니다.

5. Reducing Overhead & Startup Time

불필요한 CPU 사이클을 줄이고 기동 시간을 단축하기 위한 설정입니다.

Servlet Response Time

WebContainer가 정적 리소스 처리를 위해 META-INF 디렉토리를 스캔하는 과정을 생략합니다.

<webContainer skipMetaInfResourcesProcessing="true"/>

Idle Server CPU

운영 환경에서는 빈번한 애플리케이션/구성 파일 변경 감지가 불필요하므로, 모니터링 주기를 비활성화하거나 늘립니다.

<!-- 아예 비활성화 (권장) -->
<applicationMonitor dropinsEnabled="false" updateTrigger="disabled"/>
<config updateTrigger="disabled"/>

<!-- 혹은 MBean 트리거로 변경 및 폴링 주기 완화 -->
<applicationMonitor updateTrigger="mbean" pollingRate="60s"/>
<config updateTrigger="mbean" monitorInterval="60s"/>

CDI 1.2 Scanning

CDI 1.2 기능은 기본적으로 모든 아카이브를 스캔합니다. 대규모 애플리케이션에서 기동 속도 저하의 주원인이 되므로, 암시적 스캔(Implicit Bean Archives)을 비활성화합니다.

<cdi12 enableImplicitBeanArchives="false"/>

Next Step: 위 설정들은 워크로드의 특성에 따라 효과가 다릅니다. 운영 환경 적용 전, 부하 테스트를 통해 각 파라미터 변경에 따른 처리량(Throughput)과 응답 시간 변화를 측정하시기 바랍니다.

Open Stream →
#Liberty

[WebSphere] Liberty Cluster: End-to-End 구축 및 구성 가이드

Summary: WebSphere Liberty Profile(WLP)의 Collective 및 Cluster 기능을 활용한 인프라 구축 가이드입니다. Controller 구성부터 Member 조인, 클러스터링 설정 및 트러블슈팅까지의 전체 과정을 다룹니다.

WebSphere Application Server Liberty Profile(WLP)은 경량화된 구조와 확장성 덕분에 채택률이 높아지고 있습니다. 본 포스트는 WLP Collective와 Clustering 기능을 사용하여 확장 가능한 토폴로지를 구축하는 방법을 단계별로 정리한 엔지니어링 노트입니다.

이 시리즈는 다음 순서로 진행됩니다.

  • How to Create and Configure WebSphere Liberty Cluster End-to-End (Current)
  • How to Deploy Application in WebSphere Liberty Cluster
  • How to Setup Front-End Web Server for WebSphere Liberty Cluster

1. Topology Architecture

이 가이드에서는 Collective Controller 1대와 Collective/Cluster Member 2대로 구성된 토폴로지를 구현합니다. 프론트엔드에는 IBM HTTP Server(IHS)가 배치되며 별도의 배포 서버가 존재하는 구조입니다.

2. Prerequisites & WLP Installation

본 가이드는 WLP 17.0.2CentOS Linux 7.3 환경을 기준으로 작성되었습니다. 설치 전 지원되는 Java 버전이 설치되어 있는지 확인이 필요합니다.

Check System Environment

$> cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

$> ./java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build pxa6480sr4fp5-20170421_01(SR4 FP5))
IBM J9 VM (build 2.8, JRE 1.8.0 Linux amd64-64 Compressed References 20170419_344392)

Base Installation (Machine: 02)

먼저 Controller가 될 머신(Machine: 02)에 WLP를 설치하고 필요한 기능을 추가한 뒤, 이를 패키징하여 Member 서버들(Machine: 03, 04)로 배포하는 전략을 사용합니다.

# Create directory
$> sudo mkdir -p /opt/ibm

# Change ownership
$> sudo chown -R wasadmin:wasgrp /opt/ibm

# Install WLP
$> java -jar wlp-17.0.0.2-all.jar --acceptLicense /opt/ibm

# Verify version
$> cd /opt/ibm/wlp/bin
$> ./productInfo version
Product name: WebSphere Application Server
Product version: 17.0.0.2

Install Required Features

Collective, Cluster, SSL, JMX Connector 등의 필수 기능을 설치합니다.

$> ./installUtility install collectiveController-1.0 collectiveMember-1.0 clusterMember-1.0 websocket-1.1 restConnector-2.0 ssl-1.0 localConnector-1.0 adminCenter-1.0

Package and Distribute

설치된 환경을 wlp_install.jar로 패키징하여 다른 노드에 복제합니다.

# Create defaultServer for packaging context
$> ./server create

# Package server including all binaries
$> ./server package defaultServer --archive=/tmp/wlp_install.jar --include=all
Server defaultServer package complete in /tmp/wlp_install.jar.

생성된 wlp_install.jar를 Machine 03, 04로 전송한 후 동일하게 설치를 진행합니다.

# On Machine 03 & 04
$> sudo mkdir -p /opt/ibm
$> chown -R wasadmin:wasgrp /opt/ibm
$> java -jar wlp_install.jar --acceptLicense /opt/ibm

3. Setup Collective Controller (Machine: 02)

Controller 서버(wlpCntlr)를 생성하고 구성을 초기화합니다.

# Create server
$> ./server create wlpCntlr

# Initialize Collective Controller
$> ./collective create wlpCntlr --keystorePassword=<password> --createConfigFile=/opt/ibm/wlp/usr/servers/wlpCntlr/wlpcntlr_include.xml

위 명령어를 수행하면 인증서 생성 및 wlpcntlr_include.xml 설정 파일이 생성됩니다. 이후 server.xml과 include 파일을 다음과 같이 수정합니다.

Configuration: server.xml (Controller)

<server description="CollectiveController">
    <featureManager>
        <feature>adminCenter-1.0</feature>
        <feature>websocket-1.1</feature>
        <feature>restConnector-1.0</feature>
        <feature>localConnector-1.0</feature>
    </featureManager>

    <!-- Include generated config -->
    <include location="${server.config.dir}/wlpcntlr_include.xml" />

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" host="*" />
</server>

Configuration: wlpcntlr_include.xml

자동 생성된 파일에서 quickStartSecurity 부분을 본인의 계정 정보로 수정합니다.

<quickStartSecurity userName="wasadmin" userPassword="{xor}EncryptedPassword..." />

Firewall Configuration

CentOS 방화벽에서 9080, 9443 포트를 허용해야 합니다.

$> sudo firewall-cmd --zone=public --permanent --add-port=9443/tcp
$> sudo firewall-cmd --zone=public --permanent --add-port=9080/tcp
$> sudo firewall-cmd --reload

Start Controller

$> ./server start wlpCntlr

로그(messages.log)에서 CWWKX6011I: The collective controller is ready 메시지를 확인합니다. Admin Center(https://hostname:9443/adminCenter/) 접속도 가능해야 합니다.

4. Setup Collective & Cluster Members

Machine 03과 04에서 멤버 서버를 생성하고 Controller에 Join 시킵니다.

Create & Join Member (Machine: 03)

# Create Server
$> ./server create wlpSrv01

# Join Collective
$> ./collective join wlpSrv01 \
  --host=waslibctlr01 \
  --port=9443 \
  --user=wasadmin \
  --password=<password> \
  --keystorePassword=<password> \
  --createConfigFile=/opt/ibm/wlp/usr/servers/wlpSrv01/wlpsrv01_include.xml

SSL Handshake 과정에서 인증서를 신뢰하겠냐는 프롬프트에 y를 입력합니다.

Configuration: server.xml (Member)

Member 서버의 server.xml에 Cluster 기능을 추가하고, Controller가 배포 관리를 할 수 있도록 remoteFileAccess를 설정합니다.

<server description="Cluster Member">
    <featureManager>
        <feature>webProfile-7.0</feature>
        <feature>restConnector-1.0</feature>
        <feature>localConnector-1.0</feature>
        <!-- Added for Clustering -->
        <feature>clusterMember-1.0</feature>
    </featureManager>

    <include location="${server.config.dir}/wlpsrv01_include.xml" />

    <!-- Define Cluster Name -->
    <clusterMember name="wlpCluster"/>

    <httpEndpoint id="defaultHttpEndpoint" httpPort="9081" httpsPort="9444" host="*" />

    <!-- Write Access for Controller -->
    <remoteFileAccess>
        <writeDir>${server.config.dir}</writeDir>
    </remoteFileAccess>
</server>

Machine: 04 (wlpSrv02)에 대해서도 위 과정을 동일하게 반복합니다.

Security Considerations (LTPA)

클러스터 환경에서 세션 공유 및 보안을 위해 모든 멤버는 동일한 LTPA 키를 사용해야 합니다. 한 서버에서 생성된 ltpa.keys 파일을 다른 멤버 서버들의 동일한 경로(${server.ouput.dir}/resources/security/)로 복사합니다.

5. Start Members & Verification

각 노드에서 멤버 서버를 시작합니다.

$> ./server start wlpSrv01  # On Machine 03
$> ./server start wlpSrv02  # On Machine 04

로그 파일에서 다음 메시지들을 확인하여 정상 구동을 검증합니다.

  • CWWKX8112I: Collective Repository에 호스트 정보 게시 성공.
  • CWWKX7400I: ClusterMember MBean 활성화 (클러스터 조인 성공).

6. Troubleshooting Notes

설정 과정에서 자주 발생하는 오류와 해결 방법입니다.

  • CWWKX0229E (401 Unauthorized / 403 Forbidden)
    collective join 시 인증 실패. quickStartSecurity의 계정 정보가 일치하는지 확인하십시오. 403 에러의 경우 해당 사용자가 administrator-role을 가지고 있는지 확인해야 합니다.
  • CWWKS9582E (SSL unresolved)
    IIOP 보안 설정 시 SSL 참조 오류. server.xml에 SSL 구성 및 KeyStore 정의가 명확한지 확인하십시오.
  • CWWKO0221E / CWWKS9580E (Port in use)
    한 호스트에 여러 인스턴스를 띄울 경우 JMS 포트(7276)나 IIOP 포트(2809) 충돌이 발생할 수 있습니다. wasJmsEndpointiiopEndpoint 설정을 통해 포트를 변경해야 합니다.

Next Step: 클러스터 구성이 완료되었습니다. 다음 포스트에서는 이 클러스터에 애플리케이션을 배포하는 방법을 다룹니다.

Open Stream →
#Liberty

[IHS/Liberty] 보안 취약점 조치: X-Powered-By 헤더 숨김 및 정보 노출 방지 가이드

IBM HTTP Server(IHS)와 WebSphere Liberty 환경에서 X-Powered-By 헤더(예: Servlet/3.1) 노출을 차단하는 방법을 정리합니다. 보안 강화를 위해 웹 서버(IHS) 단에서의 필터링과 WAS(Liberty) 단에서의 생성 금지 설정을 모두 적용하는 것을 권장합니다.

0. 배경 및 전략 (Context)

보안 취약점 조치 시, 정보 노출 방지는 다계층 방어(Defense in Depth)가 중요합니다.

계층 역할 및 중요성
1. IHS (Web Server) [필수] 최전방 방어선. 백엔드 WAS가 무엇이든 상관없이 클라이언트로 나가는 모든 응답에서 헤더를 강제 삭제합니다.
2. Liberty (WAS) [권장] 소스 차단. 내부망에서 WAS로 직접 접속하는 경우나 웹 서버 설정을 우회하는 경우를 대비해 헤더 생성 자체를 막습니다.

Test Environment

  • Web Server: IBM HTTP Server v9.0 (Apache 2.4 Base)
  • WAS: WebSphere Liberty Core 20.0.x

1. IBM HTTP Server (IHS) 설정

Apache 기반인 IHS에서는 mod_headers 모듈을 사용하여 응답 헤더를 제어합니다.

httpd.conf 수정

설정 파일(httpd.conf)을 열어 아래 내용을 적용합니다.

# 1. 모듈 로드 확인 (주석 해제 필수)
LoadModule headers_module modules/mod_headers.so

# 2. 헤더 제거 설정 (Global 영역 또는 VirtualHost 내부에 작성)
<IfModule mod_headers.c>
    # 보안 조치: 기술 스택 정보 숨김
    Header unset X-Powered-By
    
    # (선택) 추가적인 정보 노출 헤더 차단
    Header unset X-AspNet-Version
    Header unset X-Runtime
</IfModule>

# 3. 서버 버전 정보 최소화 (OS 정보 등 숨김)
ServerTokens Prod
Tip: 설정 후에는 반드시 ./apachectl -t로 문법을 검사하고 재기동(restart 또는 graceful)해야 합니다.

2. WebSphere Liberty 설정

Liberty는 server.xml 파일 하나로 대부분의 설정을 처리합니다. webContainer 요소를 추가하거나 수정하여 헤더 생성을 비활성화합니다.

server.xml 수정

<server description="Liberty Server">

    <!-- Feature Manager (기본 설정) -->
    <featureManager>
        <feature>servlet-3.1</feature>
    </featureManager>

    <!-- [보안 조치] X-Powered-By 헤더 비활성화 속성 추가 -->
    <webContainer disableXPoweredBy="true" />

</server>

Liberty는 동적 설정을 지원하므로 파일 저장 시 즉시 반영되지만, 운영 환경에서는 확실한 적용을 위해 서버 재기동을 권장합니다.


3. 검증 (Verification)

curl 명령어를 사용하여 조치 전후의 응답 헤더를 비교합니다.

조치 전 (Before)

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1
Server: IBM_HTTP_Server/9.0.5...
...

조치 후 (After)

curl -I http://localhost:80/
HTTP/1.1 200 OK
Server: IBM_HTTP_Server   <-- (Prod 설정으로 버전 숨김)
Content-Type: text/html
...                       <-- (X-Powered-By 헤더 삭제됨)

Next Step:
헤더 조치가 완료되었다면, HTTP 메소드 제한(GET, POST 외 차단)SSL/TLS 프로토콜 버전(TLS 1.2 Only) 설정을 통해 웹 서비스 보안을 한 단계 더 강화해 보십시오.

Open Stream →
#Liberty

[WebSphere Liberty] securityUtility로 SSL 인증서 생성 및 AES 패스워드 암호화 설정 가이드

WebSphere Liberty의 securityUtility 도구를 사용하여 자체 서명된(Self-Signed) SSL 인증서를 생성하고, 보안성을 높이기 위해 Keystore 비밀번호를 AES로 암호화하여 설정하는 방법을 정리합니다.

0. 배경 및 시나리오 (Context)

Liberty 서버는 기본적으로 개발 편의를 위해 SSL 설정을 자동화하지만, 운영 환경에서는 명시적인 인증서 관리와 비밀번호 보안이 필수적입니다. securityUtility를 사용하면 인증서 생성과 비밀번호 암호화(Encoding)를 동시에 수행할 수 있습니다.

Test Environment

  • Middleware: WebSphere Liberty Profile (WLP)
  • Server Name: s11, s12

1. SSL 인증서 생성 및 암호화 (Create Certificate)

securityUtility createSSLCertificate 명령어를 사용하여 키스토어(PKCS12)를 생성합니다. 이때 --passwordEncoding=aes 옵션을 사용하여 설정 파일에 들어갈 비밀번호를 암호화합니다.

명령어 구문

# 구문: securityUtility createSSLCertificate --server=[서버명] --password=[키패스워드] --validity=[유효기간일수] --passwordEncoding=aes --passwordKey=[암호화키]

cd $WLP_HOME/bin
./securityUtility createSSLCertificate --server=s11 --password=passw0rd --validity=7300 --passwordEncoding=aes --passwordKey=passw0rd

실행 결과

키 저장소 /sw/was/WebSphere/wlp/usr/servers/s11/resources/security/key.p12을(를) 작성하는 중입니다.

서버 s11에 대한 SSL 인증서를 작성했습니다. 
이 인증서는 CN=testwas11,OU=s11을(를) 사용하여 SubjectDN으로 작성되었습니다.
Tip: 여기서 생성된 키스토어 파일(key.p12)은 usr/servers/[서버명]/resources/security/ 경로에 저장됩니다.

2. 서버 설정 적용 (server.xml)

위에서 생성된 인증서를 서버가 사용하도록 server.xml을 수정합니다. 이때 비밀번호 부분에 {aes}... 로 시작하는 암호화된 문자열을 입력해야 합니다.

<server description="SSL Server">

    <!-- 1. SSL 기능 활성화 -->
    <featureManager>
        <feature>transportSecurity-1.0</feature>
    </featureManager>

    <!-- 2. Keystore 정의 (비밀번호는 암호화된 값 사용) -->
    <keyStore id="defaultKeyStore" 
              location="key.p12"
              password="{aes}AJS+VEek/Fgo/zp46z8cuIUMTbnMM7sJVmPPbT49n4s6" />

</server>

3. 암호화 키 등록 (bootstrap.properties)

server.xml에 적힌 {aes} 비밀번호를 서버가 복호화하려면, 암호화할 때 사용했던 Key를 서버에 알려주어야 합니다. 이 설정은 bootstrap.properties 파일에 저장합니다.

  • 파일 위치: usr/servers/[서버명]/bootstrap.properties
# securityUtility 실행 시 --passwordKey 옵션에 넣었던 값
wlp.password.encryption.key=passw0rd
주의: 이 설정이 누락되면 서버 기동 시 CWWKS1704E: 비밀번호를 복호화할 수 없습니다. 에러가 발생합니다.

4. 인증서 검증 (Verification)

생성된 키스토어 파일이 정상적인지, 유효기간은 맞는지 확인하기 위해 JDK에 포함된 keytool 명령어를 사용합니다.

검증 명령어

# keytool -list -v -keystore [파일경로] -storetype PKCS12 -storepass [비밀번호]
./keytool -list -v -keystore /sw/was/WebSphere/wlp/usr/servers/s12/resources/security/key.p12 -storetype PKCS12 -storepass passw0rd

출력 결과 분석

키 저장소 유형: PKCS12
키 저장소 제공자: SUN

별칭 이름: default
생성 날짜: 2024. 6. 12.
항목 유형: PrivateKeyEntry
인증서 체인 길이: 2

# 유효기간 확인
적합한 시작 날짜: Wed Jun 12 16:47:57 KST 2024 
종료 날짜: Tue Jun 07 16:47:57 KST 2044 (약 20년)

# 소유자 및 서명 알고리즘 확인
소유자: CN=testwas11, OU=s12, O=ibm, C=us
서명 알고리즘 이름: SHA256withRSA
주체 공용 키 알고리즘: 2048비트 RSA 키

Next Step:
자체 서명 인증서(Self-Signed)는 브라우저에서 경고가 발생하므로, 운영 환경에서는 CSR을 생성하여 공인 인증기관(CA)의 서명을 받은 후 keytool -import 명령어로 교체해야 합니다.

Open Stream →
#Troubleshooting

[WebSphere] native_stderr 로그 비대화 해결: Verbose GC 로그 분리 및 로테이션 설정

WebSphere의 native_stderr.log 파일에는 로테이션(Rotation) 기능이 내장되어 있지 않습니다. 따라서 Verbose GC가 활성화된 경우 파일 용량이 무한정 증가합니다. 이를 해결하기 위해 JVM 옵션을 사용하여 GC 로그를 별도 파일로 분리하고 순환시키는 방법을 정리합니다.

1. 원인 분석 (Root Cause)

WebSphere는 SystemOut.logSystemErr.log에 대해서는 시간/크기 기반의 로그 순환을 지원합니다. 하지만, JVM 프로세스 자체의 출력을 담는 native 로그는 WAS가 제어하지 못합니다.

  • 문제점: 관리 콘솔에서 "Verbose garbage collection"을 체크하면, GC 수행 기록이 native_stderr.log에 누적됩니다.
  • 결과: 시간이 지남에 따라 파일이 GB 단위로 커지며, 디스크 Full 장애를 유발할 수 있습니다.

Test Environment

  • OS: CentOS 7 (3.10.0-957.el7.x86_64)
  • WAS: WebSphere Application Server v8.5 / 9.0
  • JDK: IBM JDK (WebSphere 기본)

2. 해결 방법: GC 로그 분리 설정

해결의 핵심은 native 로그에 GC 내용을 남기지 않고, 별도의 파일로 빼내는 것입니다. 사용하는 JDK 벤더에 따라 옵션이 다릅니다.

Step 1: 기본 Verbose GC 비활성화

JVM 옵션으로 제어하기 위해, 콘솔의 체크박스 옵션은 해제해야 합니다.

  • 경로: 서버 > 서버 유형 > WebSphere Application Server > [서버명] > Java 및 프로세스 관리 > 프로세스 정의 > Java 가상 머신
  • 조치: Verbose garbage collection 체크박스 해제 (Uncheck)
Disable Verbose GC Checkbox

[그림] 기본 Verbose GC 옵션 해제

Step 2: 일반 JVM 인수(Generic JVM arguments) 추가

같은 화면의 Generic JVM arguments 입력란에 아래 옵션을 추가합니다.

Case A: IBM JDK 사용 시 (WebSphere 기본)

IBM JDK는 -Xverbosegclog 옵션을 사용하여 로그 파일 경로와 로테이션 규칙을 지정합니다.

# 구문: -Xverbosegclog:[경로/파일명][,X,Y]
# X: 파일 개수, Y: 파일당 GC 사이클 수

# 예시 1: 날짜/PID 포함하여 단일 파일 생성 (가장 일반적)
-Xverbosegclog:${SERVER_LOG_ROOT}/gc.%Y%m%d.%H%M%S.%pid.txt

# 예시 2: 10,000 사이클마다 파일 교체, 총 10개 파일 유지 (로테이션)
-Xverbosegclog:${SERVER_LOG_ROOT}/verbosegc.log,10,10000

Case B: Oracle/HotSpot JDK 사용 시

드물지만 Solaris나 특정 환경에서 HotSpot 계열 JDK를 사용하는 경우입니다.

-verbose:gc
-Xloggc:${SERVER_LOG_ROOT}/verbosegc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=20M
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
Tip: ${SERVER_LOG_ROOT} 변수를 사용하면 하드코딩된 경로 대신 각 서버의 로그 디렉토리를 자동으로 찾아가므로 관리가 용이합니다.

3. 적용 확인 (Verification)

  1. 설정 저장 후 서버를 재기동합니다.
  2. ps -ef | grep java 명령어로 프로세스를 확인했을 때, 추가한 옵션이 적용되어 있는지 확인합니다.
  3. 로그 디렉토리(logs/[서버명]/)에 gc...txt 또는 설정한 이름의 파일이 생성되는지 확인합니다.
GC Log File Created

Next Step:
분리된 GC 로그 파일은 IBM GCMV (Garbage Collection and Memory Visualizer) 도구에 넣어 분석하면 메모리 누수나 튜닝 포인트를 시각적으로 확인할 수 있습니다.

Open Stream →
#security

[WebSphere] Log4j 보안 취약점(Log4Shell) 긴급 대응: kc.war 및 uddi.ear 조치 가이드

Apache Log4j 취약점(CVE-2021-44228 등)이 IBM WebSphere Application Server(WAS)에 미치는 영향을 분석합니다. WAS 9.0의 관리 콘솔 도움말(kc.war)과 전 버전의 UDDI 레지스트리(uddi.ear)에 포함된 취약한 라이브러리를 제거하는 임시 조치(Mitigation) 방법을 정리합니다.

1. 영향받는 제품 및 버전 (Affected Products)

사실상 현재 운영 중인 대부분의 WebSphere 버전이 직간접적인 영향권에 있습니다.

제품 (Product) 영향 버전 (Versions)
WebSphere Application Server (Traditional) 9.0, 8.5, 8.0, 7.0
WebSphere Liberty Continuous Delivery (All)

2. 취약점 상세 및 조치 가이드 (Remediation)

WAS 엔진 자체보다는 번들로 제공되는 특정 애플리케이션 내의 라이브러리가 문제입니다. 사용하지 않는 기능이라면 과감하게 삭제하는 것이 가장 확실한 방법입니다.

Case A: WAS 9.0 - kc.war (관리 콘솔 도움말)

WAS 9.0 관리 콘솔의 '도움말(Knowledge Center)' 기능에 Log4j 2.x 취약 버전이 포함되어 있습니다.

  • 대상: WAS 9.0 사용자
  • 조치 방법: 해당 라이브러리 파일 삭제
# 1. 배포된 디렉토리에서 라이브러리 제거
rm -f [WAS_HOME]/systemApps/isclite.ear/kc.war/WEB-INF/lib/log4j*.jar

# 2. 설치 가능 앱 디렉토리에서 원본 앱 제거 (재설치 방지)
rm -rf [WAS_HOME]/installableApps/kc.war

# 3. 서버 재기동
./stopServer.sh server1 && ./startServer.sh server1
주의: 향후 9.0.5.11 이전의 픽스팩을 적용하면 삭제한 파일이 복구될 수 있으므로, 패치 후 다시 확인해야 합니다.

Case B: 전 버전 - uddi.ear (UDDI 레지스트리)

UDDI(Universal Description, Discovery, and Integration) 서비스에 Log4j 라이브러리가 포함되어 있습니다. 대부분의 최신 환경에서는 사용하지 않는 기능입니다.

  • 대상: WAS 7.0 ~ 9.0 전체
  • 조치 방법: 사용하지 않는다면 파일 삭제
# 미사용 시 (권장)
rm -f [WAS_HOME]/installableApps/uddi.ear

# 사용 중일 경우 (라이브러리만 교체/삭제 후 재배포 필요)
# uddi.ear 압축 해제 -> log4j*.jar 삭제 -> 다시 압축 -> Redeploy

3. Log4j 1.x 관련 추가 조치 (CVE-2021-4104)

Log4j 1.x 버전은 Log4Shell(RCE) 취약점의 직접적인 대상은 아니지만, JMSAppender를 사용할 경우 유사한 공격이 가능합니다. (WAS 기본 설정에는 JMSAppender가 없으나, 애플리케이션에서 사용할 수 있음)

조치 방법 (JMSAppender 제거)

Log4j 1.x는 더 이상 보안 패치가 나오지 않으므로(EOL), 취약한 클래스 파일만 강제로 삭제하는 것이 유일한 방법입니다.

# 시스템 전체에서 log4j-1.2.x.jar 파일을 찾아 JMSAppender 클래스 제거
zip -q -d log4j-1.2.17.jar org/apache/log4j/net/JMSAppender.class

4. 참고 자료 (Reference)

Summary:
WAS 운영팀은 kc.waruddi.ear 내의 log4j 파일을 삭제하고, 개발팀은 배포하는 애플리케이션(WAR/EAR) 내에 취약한 Log4j 버전이 포함되지 않도록 빌드 의존성을 점검해야 합니다.
Open Stream →
#security

[WebSphere] 보안 감사 대응: NCSA Access Log 활성화 및 로그 포맷(User-Agent, Time) 커스터마이징

WebSphere v8.5 환경에서 보안 감사 및 트러블슈팅을 위해 NCSA Access Log를 활성화하는 방법을 정리합니다. 서버 전역 설정과 전송 체인(Transport Chain)별 설정을 모두 적용해야 하며, accessLogFormat 속성을 통해 클라이언트 IP, 수행 시간, User-Agent 등을 기록하도록 포맷을 변경하는 방법을 다룹니다.

0. 배경 및 필요성 (Context)

WAS 앞단에 웹 서버(Web Server)가 있다면 웹 서버 로그를 분석하면 되지만, WAS로 직접 들어오는 요청이나 내부 통신, 혹은 상세한 애플리케이션 수행 시간 분석을 위해서는 WAS 자체의 Access Log가 필요합니다. WebSphere는 NCSA 표준 포맷을 지원합니다.

Test Environment

  • Version: WebSphere Application Server v8.5

1. 전역 로깅 서비스 활성화 (Global Setting)

가장 먼저 서버 차원에서 로깅 서비스를 켜야 합니다.

  1. 관리 콘솔에서 Servers > Server Types > WebSphere application servers > [서버명] 클릭
  2. 우측 하단의 Troubleshooting 섹션에서 NCSA access and HTTP error logging 클릭
  3. 설정 체크:
    • Enable logging service at server start-up (서버 기동 시 서비스 활성화)
    • Enable access logging (액세스 로깅 활성화)
NCSA Logging Global Setting

2. 전송 체인별 로깅 활성화 (Chain Setting)

전역 설정을 했더라도, 실제 통신을 담당하는 전송 체인(Transport Chain)에서 로깅을 켜지 않으면 로그가 남지 않는 경우가 많습니다. 사용하는 포트(9080, 9443 등)에 해당하는 체인을 수정해야 합니다.

설정 경로

[서버명] > Web Container Settings > Web container transport chains

설정 방법

주로 사용되는 체인(WCInboundDefault, HttpQueueInboundDefault 등)을 선택하여 아래 작업을 반복합니다.

  1. 체인 이름 클릭 (예: WCInboundDefault)
  2. HTTP inbound channel (HTTP_2) 클릭
  3. Enable logging 체크박스 선택
Chain Selection Enable Logging Checkbox
Tip: HTTPS(SSL) 요청에 대한 로그도 남기려면 WCInboundDefaultSecure 체인에 대해서도 동일하게 설정해야 합니다.

3. 로그 포맷 커스터마이징 (Custom Properties)

기본 포맷(Common Log Format)은 정보가 부족할 수 있습니다. 수행 시간이나 세션 ID, User-Agent 등을 남기기 위해 사용자 정의 속성을 추가합니다.

속성 추가 위치

위의 HTTP inbound channel (HTTP_2) 설정 화면에서 우측의 Custom properties (사용자 정의 특성) 메뉴로 진입합니다.

속성 값 (Key & Value)

  • Name: accessLogFormat
  • Value: (아래 예시 중 선택)
# 예시 1: 표준 확장 포맷 (IP, 시간, 요청, 상태, 크기, 수행시간)
%h %u %t "%r" %s %b %D

# 예시 2: 전체 정보 포함 (Referer, User-Agent, SessionID 포함)
%h %u %t "%r" %s %b %D "%{Referer}i" "%{User-agent}i" %{JSESSIONID}C
Custom Properties List

Setting accessLogFormat

4. 주요 포맷 지시어 설명

지시어 설명
%h 클라이언트 IP 주소 (Host)
%t 요청 시간 (Time)
%r 요청 라인 (Request Line) - Method, URI, Protocol
%s 응답 상태 코드 (Status Code, 예: 200, 404, 500)
%D 요청 처리 소요 시간 (마이크로초 단위, 성능 분석 시 중요)
%{Header}i 특정 요청 헤더 값 (예: %{User-Agent}i)
%{Cookie}C 특정 쿠키 값 (예: %{JSESSIONID}C)

Next Step:
모든 설정을 마친 후에는 반드시 서버를 재기동해야 로그가 남기 시작합니다. logs/[서버명]/http_access.log 파일이 생성되는지 확인하십시오.

Open Stream →
#security

[WebSphere] TLS 1.2 전환 완벽 가이드: 버전별 지원 현황 및 WAS/IHS/Plugin 필수 설정

WebSphere Application Server v7.0, v8.0, v8.5 환경에서 TLS 1.2 프로토콜을 활성화하기 위한 최소 요구 사항(Fix Pack, JDK)을 확인하고, WAS, IHS, Plugin 각 계층별 필수 설정 방법을 정리합니다. 특히 플러그인 연결 시 발생하는 GSK_ERROR_SOCKET_CLOSED 에러 해결법을 포함합니다.

1. 버전별 TLS 1.2 지원 현황 (Prerequisites)

TLS 1.2를 사용하려면 WAS 버전에 따른 최소 픽스팩(Fix Pack)과 JDK 버전이 충족되어야 합니다.

WAS Version Minimum Fix Pack Required SDK Version
v7.0 7.0.0.23 이상 SDK 6 SR10 FP1 이상
v8.0 8.0.0.3 이상 SDK 6.0.1 (J9 2.6) SR1 FP1 이상
v8.5 8.5.0.0 (기본 지원) SDK 6.0.1 (J9 2.6) SR2 이상
주의 (v7.0 제한사항):
WAS v7.0은 Java 레벨에서는 TLS 1.2를 지원하지만, 함께 제공되는 Web Server Plugin(GSKit V7 사용)은 TLS 1.2를 지원하지 않습니다. 따라서 v7.0 환경에서 웹 서버 연동 구간까지 TLS 1.2를 적용하려면 Plugin 모듈 업그레이드 혹은 아키텍처 검토가 필요할 수 있습니다.

2. WAS 설정 (Application Server)

관리 콘솔에서 SSL 설정을 변경하고, 관리 명령(stop/sync) 수행을 위해 클라이언트 설정 파일도 함께 수정해야 합니다.

1) 관리 콘솔 설정 (QoP)

Security > SSL certificate and key management > SSL configurations 메뉴로 이동합니다. CellDefaultSSLSettings, NodeDefaultSSLSettings 등 사용 중인 모든 설정을 수정합니다.

  1. 설정 이름 클릭 (예: CellDefaultSSLSettings)
  2. 우측의 Quality of protection (QoP) settings 클릭
  3. Protocol 드롭다운 메뉴에서 TLSv1.2 선택
  4. 저장 (Save)

2) ssl.client.props 수정 (중요)

이 설정을 하지 않으면 WAS가 TLS 1.2로 전환된 후, stopNodesyncNode 같은 관리 명령어가 구형 프로토콜로 통신을 시도하여 실패하게 됩니다.

  • 대상 파일:
    • [PROFILE_HOME]/properties/ssl.client.props
# 파일 내 해당 라인 수정
com.ibm.ssl.protocol=TLSv1.2

3) 재기동 및 동기화

설정 적용을 위해 DMGR부터 순서대로 재기동합니다.

# 1. 노드 및 DMGR 중지
./stopNode.sh
./stopManager.sh

# 2. DMGR 기동
./startManager.sh

# 3. 노드 동기화 (수동 동기화 권장)
./syncNode.sh [Dmgr_Host] [Dmgr_SOAP_Port] -username [ID] -password [PW]

# 4. 노드 기동
./startNode.sh

3. Web Server (IHS) 설정

IBM HTTP Server의 httpd.conf 파일에서 SSL 설정을 강화합니다.

<VirtualHost *:443>
    SSLEnable
    
    # TLS 1.2 활성화
    SSLProtocolEnable TLSv12
    
    # 취약한 하위 프로토콜 비활성화
    SSLProtocolDisable SSLv2 SSLv3 TLSv10 TLSv11
</VirtualHost>

4. Plugin 설정 (Troubleshooting)

WAS와 IHS를 모두 TLS 1.2로 설정했는데도 http_plugin.logGSK_ERROR_SOCKET_CLOSED (gsk rc = 420) 에러가 발생하며 연결이 안 될 수 있습니다. 이는 플러그인이 기본적으로 보안 수준을 엄격하게 검사하지 않아서 발생하는 호환성 문제입니다.

해결 방법: StrictSecurity 적용

plugin-cfg.xml 파일의 최상단 Config 태그에 속성을 추가해야 합니다.

<Config StrictSecurity="true">
    <Log LogLevel="Error" Name="..." />
    ...
</Config>
Tip: StrictSecurity="true" 설정은 플러그인이 WAS와 통신할 때 TLS 프로토콜을 엄격하게 준수하도록 강제하여, TLS 1.2 핸드쉐이크 문제를 해결합니다.

5. 검증 (Verification)

openssl 명령어를 사용하여 서버가 TLS 1.2만 허용하는지 테스트합니다.

# TLS 1.2 접속 성공 확인
openssl s_client -connect [Host]:9443 -tls1_2

# TLS 1.0 접속 실패 확인 (핸드쉐이크 에러가 나야 정상)
openssl s_client -connect [Host]:9443 -tls1
Open Stream →
#Liberty

[WebSphere Liberty] installUtility 사용법 완벽 가이드: Feature 검색, 다운로드 및 로컬 저장소 구성

WebSphere Liberty의 기능(Feature)을 관리하는 커맨드 라인 도구인 installUtility의 핵심 사용법을 다룹니다. 온라인 IBM 저장소에서 기능을 검색/다운로드하는 방법과, 사내 폐쇄망 환경을 위한 로컬 리포지토리(Local Repository) 설정 방법을 정리합니다.

Test Environment

  • OS: CentOS 7.2
  • Middleware: IBM Liberty Core 20.0.0.6
  • Tool: installUtility (Located in $WLP_HOME/bin)

1. Feature 검색 및 다운로드 (Basic Usage)

IBM의 공인 저장소(IBM WebSphere Liberty Repository)에 연결하여 필요한 기능을 찾거나 다운로드합니다.

기능 검색 (Find)

설치 가능한 기능의 정확한 이름을 모를 때 유용합니다.

# 구문: installUtility find [검색어]
installUtility find jsp --type=feature

기능 다운로드 (Download)

서버에 바로 설치하지 않고, 파일(ESA) 형태로 로컬 디렉토리에 다운로드합니다. 이 파일들은 나중에 로컬 저장소를 구축할 때 사용됩니다.

# 구문: installUtility download [기능명] --location=[경로]
installUtility download jsp-2.3 --location=/SW/img/LibertyUtility --acceptLicense

2. 로컬 저장소 구성 (Repository Configuration)

인터넷이 차단된 서버나, 사내 표준 라이브러리를 관리하기 위해 로컬 디렉토리를 저장소로 등록하여 사용합니다.

설정 파일 위치

Liberty 설치 경로 내의 etc 디렉토리에 설정 파일을 생성해야 합니다.

  • 위치: ${wlp.install.dir}/etc/repositories.properties

설정 내용 (repositories.properties)

다운로드 받아둔 Feature 파일들이 위치한 경로를 url로 지정합니다.

# Local Repository Path Configuration
# 로컬 파일 시스템 경로 또는 사내 웹 서버 URL 지정 가능
local-rep.url=/SW/img/LibertyUtility
Tip: useDefaultRepository=false 옵션을 추가하면 IBM 공인 저장소 접속을 차단하고 로컬 저장소만 바라보게 강제할 수 있습니다.

3. 설정 검증 (Verification)

작성한 리포지토리 설정이 정상적으로 인식되는지 확인합니다.

설정 확인 (viewSettings)

현재 적용된 리포지토리 목록과 우선순위를 출력합니다.

installUtility viewSettings

(출력 결과에서 local-rep.url이 목록에 포함되어 있는지 확인)

연결 테스트 (testConnection)

지정한 경로로 접근이 가능한지 최종 테스트합니다.

# 특정 저장소 테스트
installUtility testConnection local-rep

# 또는 전체 테스트
installUtility testConnection --all

4. 참고 자료 (References)


Next Step:
로컬 저장소 구성이 끝났다면, installUtility install [기능명] 명령어를 통해 인터넷 연결 없이도 필요한 기능을 서버에 즉시 설치해 보십시오.

Open Stream →
#IBM HTTPServer

[WebSphere] WAS v9.0 CLI 설치 완벽 가이드: IM, WAS, IHS, Plugin 및 JDK 8 동시 설치

CentOS 7 환경에서 GUI 없이 imcl 명령어를 사용하여 WebSphere v9.0.5.1을 설치합니다. v9.0부터 변경된 정책에 따라 JDK 8을 반드시 함께 설치해야 함을 강조하며, WAS, IHS, Plugin 설치 및 패치 적용 명령어를 정리합니다.

Test Environment

  • OS: CentOS 7 (3.10.0-957.el7.x86_64)
  • Installer: IBM Installation Manager (IM) 1.8.x 이상
  • Target Version: WebSphere Application Server 9.0.5.1

1. Installation Manager (IM) 설치

IBM 제품군을 설치하고 관리하는 도구인 IM을 먼저 설치합니다. -repositories에는 repository.config 파일이 있는 경로를 지정합니다.

설치 명령어

# 설치 경로로 이동
cd /sw/img/im

# IM 설치 실행
./imcl install com.ibm.cic.agent \
-repositories "/sw/img/im/repository.config" \
-installationDirectory "/sw/IBM/InstallationManager/eclipse" \
-sharedResourcesDirectory "/sw/IBM/IMShared" \
-acceptLicense \
-showProgress -sP
Tip (패키지 ID 확인):
설치하려는 제품의 정확한 ID(예: com.ibm.websphere...)를 모른다면 설치 미디어 내의 Offerings 폴더를 확인하거나, ./imcl listAvailablePackages -repositories [경로] 명령어로 조회할 수 있습니다.

2. WebSphere Application Server (WAS) 설치

중요: WAS v9.0은 기본 JDK가 포함되어 있지 않습니다. 따라서 com.ibm.websphere.BASE... 패키지와 com.ibm.java.jdk.v8... 패키지를 동시에 지정하여 설치해야 합니다.

설치 명령어 (Base + JDK 8)

설치 도구(tools) 경로로 이동하여 실행합니다.

cd /sw/IBM/InstallationManager/eclipse/tools

# WAS 및 JDK 동시 설치
./imcl install com.ibm.websphere.BASE.v90_9.0.5001.20190828_0616 \
com.ibm.java.jdk.v8_8.0.5041.20190924_1031 \
-repositories "/sw/img/base","/sw/img/sdk" \
-installationDirectory "/sw/was/AppServer9" \
-sharedResourcesDirectory "/sw/IBM/IMShared" \
-acceptLicense \
-properties cic.selector.nl=ko \
-showProgress -sP

Fix Pack 업데이트 (Optional)

설치 후 특정 픽스팩(예: 9.0.5.3)으로 업데이트가 필요한 경우 아래 명령어를 사용합니다.

./imcl install com.ibm.websphere.BASE.v90_9.0.5003.20200226_0941 \
-repositories "/sw/img/fixwas" \
-installationDirectory "/sw/was/AppServer9" \
-acceptLicense -sP

3. IBM HTTP Server (IHS) 설치

웹 서버인 IHS도 마찬가지로 JDK 설치가 필요합니다. user.ihs.httpPort 속성으로 기본 포트를 지정할 수 있습니다.

# IHS 및 JDK 동시 설치
./imcl install com.ibm.websphere.IHS.v90_9.0.5001.20190828_0616 \
com.ibm.java.jdk.v8_8.0.5041.20190924_1031 \
-repositories "/sw/img/ihs","/sw/img/sdk" \
-installationDirectory "/sw/web/IHS9" \
-sharedResourcesDirectory "/sw/IBM/IMShared" \
-acceptLicense \
-properties user.ihs.httpPort="80" \
-showProgress -sP

4. Web Server Plugin (PLG) 설치

WAS와 웹 서버를 연동해주는 플러그인 모듈입니다.

# Plugin 및 JDK 동시 설치
./imcl install com.ibm.websphere.PLG.v90_9.0.5001.20190828_0616 \
com.ibm.java.jdk.v8_8.0.5041.20190924_1031 \
-repositories "/sw/img/plg","/sw/img/sdk" \
-installationDirectory "/sw/web/Plugins9" \
-sharedResourcesDirectory "/sw/IBM/IMShared" \
-acceptLicense \
-showProgress -sP

5. 설치 검증 (Verification)

모든 설치가 완료되면 설치된 패키지 목록과 상세 버전을 확인합니다.

설치된 패키지 목록 확인

# IM 명령어로 확인
./imcl listInstalledPackages

상세 버전 리포트 확인

WAS가 제공하는 스크립트로 상세 리포트를 확인합니다.

# WAS 홈의 bin 디렉토리
/sw/was/AppServer9/bin/versionInfo.sh

Next Step:
엔진 설치가 완료되었습니다. 이제 manageprofiles.sh 명령어를 사용하여 실제 서비스를 구동할 프로파일(Profile)을 생성해야 합니다.

Open Stream →
#IBM HTTPServer

[WebSphere/IHS] 보안 취약점 조치: Server 헤더 숨기기 및 버전 정보 노출 방지 전략

HTTP 응답 헤더의 Server 필드(예: Apache/2.4, WebSphere Application Server/8.5)를 통해 서버의 종류와 버전이 노출되는 것을 방지하는 방법을 정리합니다. 앞단의 IBM HTTP Server(IHS)와 뒷단의 WebSphere(WAS) 양쪽 모두의 설정이 필요합니다.

0. 배경 및 원인 (Context)

서버의 구체적인 버전 정보가 노출되면, 해커는 해당 버전에 알려진 취약점(CVE)을 찾아 맞춤형 공격을 시도할 수 있습니다. 따라서 보안 모범 사례(Best Practice)에서는 서버 정보를 숨기거나 최소화할 것을 권고합니다.

Test Environment

  • OS: CentOS 7.2
  • Web Server: IBM HTTP Server (Apache 기반)
  • WAS: WebSphere Application Server v8.5

1. IBM HTTP Server (Web Server) 설정

가장 앞단에서 요청을 받는 웹 서버의 설정을 변경합니다. httpd.conf 파일에 아래 지시어를 추가하거나 수정합니다.

설정 내용 (httpd.conf)

# 1. 서버 정보 최소화 (Apache/x.y.z -> Apache)
ServerTokens Prod

# 2. 에러 페이지 하단(Footer)에 서버 정보 숨김
ServerSignature Off

# 3. Server 헤더 자체를 응답에서 제거 (IHS 전용 기능, 가능할 경우 권장)
AddServerHeader Off
Tip: AddServerHeader Off는 표준 Apache에는 없고 IBM HTTP Server에만 존재하는 지시어일 수 있습니다. 적용 후 Syntax Error가 난다면 ServerTokens Prod까지만 적용하십시오.

2. WebSphere (WAS) 설정

WAS가 직접 클라이언트에게 응답을 줄 때 붙는 헤더를 제어합니다. WAS v8.5.0.2 이상부터는 기본 동작이 변경되었으나, 명시적으로 제어하기 위해 HTTP 전송 채널(Transport Channel) 설정을 수정합니다.

설정 경로

서버 > WebSphere Application Server > [서버명] > 웹 컨테이너 설정 > 웹 컨테이너 전송 체인 > WCInboundDefault > HTTP 인바운드 채널 (HTTP_2) > 사용자 정의 특성 (Custom properties)

주요 속성 (택 1)

상황에 맞춰 아래 두 가지 속성 중 하나를 선택하여 적용합니다.

속성 이름 (Name) 설명 및 권장 값
RemoveServerHeader 값: true
Server 헤더 자체를 아예 삭제합니다. 가장 강력한 보안 설정입니다.
ServerHeaderValue 값: (임의의 문자열)
기본값인 "WebSphere Application Server..." 대신 사용자가 지정한 문자열(예: "AppServer")로 치환합니다.
참고 (WebContainer 속성):
전송 채널 설정 외에도, 웹 컨테이너 > 사용자 정의 특성에서 com.ibm.ws.webcontainer.disableServerHeader 값을 true로 설정하는 방법도 존재합니다. (최신 버전에서 권장)

3. 검증 (Verification)

IHS와 WAS를 모두 재기동한 후, curl 명령어로 응답 헤더를 확인합니다.

# 헤더 확인
curl -I http://localhost/

# [Before]
HTTP/1.1 200 OK
Server: IBM_HTTP_Server/8.5 ...
...

# [After] 
HTTP/1.1 200 OK
# Server 헤더가 아예 없거나 "Apache" 또는 지정한 값으로 표시됨
...

Next Step:
헤더 숨김 처리가 완료되었습니다. 다음으로는 HTTP 메소드(PUT, DELETE, TRACE) 차단 설정을 통해 불필요한 요청을 막는 웹 서버 강화 작업을 진행해 보십시오.

Open Stream →
#security

[WebSphere] 보안 취약점 조치: X-Powered-By 및 Server 헤더 숨기기 설정

웹 서버 응답 헤더에 포함된 X-Powered-By 정보(예: Servlet/3.1)는 불필요한 서버 정보를 노출하여 보안 취약점으로 분류됩니다. IBM WebSphere Application Server(WAS) v8.5 이상에서 웹 컨테이너 사용자 정의 속성을 통해 이 헤더를 제거하는 방법을 정리합니다.

0. 배경 및 원인 (Context)

기본적으로 WAS는 클라이언트에게 응답을 보낼 때, 자신이 사용한 기술 스택을 헤더에 포함합니다.

  • X-Powered-By: 구현 기술 정보 (예: Servlet/3.0, JSP/2.2)
  • Server: 웹 서버 소프트웨어 정보 (예: WebSphere Application Server/8.5)

공격자는 이 정보를 바탕으로 특정 버전에 존재하는 알려진 취약점(CVE)을 공격할 수 있으므로, 운영 환경에서는 반드시 숨겨야 합니다.

Test Environment

  • OS: CentOS 7.2
  • WAS: WebSphere Application Server v8.5.5

1. X-Powered-By 헤더 제거 설정

WAS 관리 콘솔(Admin Console)에서 웹 컨테이너 설정을 변경합니다.

설정 경로

서버(Servers) > 서버 유형(Server Types) > WebSphere application servers > [서버명] > 웹 컨테이너 설정(Web Container Settings) > 웹 컨테이너(Web container) > 사용자 정의 특성(Custom properties)

속성 추가 (New)

이름 (Name) 값 (Value)
com.ibm.ws.webcontainer.disablexPoweredBy true
Tip (Server 헤더도 같이 숨기기):
보안 강도를 더 높이려면 com.ibm.ws.webcontainer.disableServerHeader 속성도 true로 설정하여 WAS 버전 정보까지 숨기는 것을 권장합니다.

2. 검증 (Verification)

설정 저장 후 서버를 반드시 재기동해야 적용됩니다. curl 명령어나 브라우저 개발자 도구(F12)를 통해 응답 헤더를 확인합니다.

명령어 확인 (Linux)

# -I 옵션으로 헤더만 조회
curl -I http://localhost:9080/

# 적용 전 (노출됨)
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0
Content-Type: text/html
...

# 적용 후 (사라짐)
HTTP/1.1 200 OK
Content-Type: text/html
...

브라우저 확인

Chrome 개발자 도구 > Network 탭 > 아무 요청 클릭 > Response Headers 섹션에서 해당 항목이 사라졌는지 확인합니다.


Next Step:
WAS 설정뿐만 아니라 앞단의 웹 서버(IHS/Apache)에서도 ServerTokens Prod 설정을 통해 Apache 버전 정보 노출을 최소화해야 완벽한 보안 조치가 됩니다.

Open Stream →
#Liberty

[WebSphere] Liberty Profile & Eclipse 연동 개발 환경 구축 가이드 (WDT 설치)

IBM WebSphere Liberty Profile(WLP)을 로컬 개발 환경인 Eclipse에 연동하여 애플리케이션 개발, 배포, 디버깅 환경을 구축하는 절차를 정리합니다. IBM WebSphere Developer Tools(WDT) 플러그인 설치 및 서버 런타임 구성 과정을 포함합니다.

Test Environment

  • OS: Windows 10
  • IDE: Eclipse IDE for Enterprise Java Developers (2020-06 이상 권장)
  • Middleware: WebSphere Liberty Profile (Kernel or Core)

1. 사전 준비 (Prerequisites)

Liberty 개발 환경을 구축하기 위해서는 Java SDK와 Eclipse가 미리 설치되어 있어야 합니다.

  • JDK: 1.8 이상 설치 및 환경 변수(JAVA_HOME) 설정.
  • Eclipse: 'Eclipse IDE for Enterprise Java and Web Developers' 패키지 사용 권장.

2. WebSphere Developer Tools (WDT) 플러그인 설치

Eclipse에서 Liberty 서버를 제어하기 위해서는 전용 플러그인을 설치해야 합니다.

설치 절차

  1. Eclipse 메뉴에서 Help > Eclipse Marketplace...를 선택합니다.
  2. 검색창에 IBM Liberty 또는 WebSphere Developer Tools를 입력합니다.
  3. "IBM Liberty Developer Tools" 항목을 찾아 Install 버튼을 클릭합니다.
  4. 라이선스 동의 후 설치를 진행하며, 완료 후 Eclipse를 재시작합니다.

3. Liberty 런타임(Runtime) 등록

이미 설치된 Liberty Core를 Eclipse에 등록하거나, Eclipse를 통해 새로 다운로드할 수 있습니다.

서버 등록 과정

  1. Servers 뷰에서 우클릭 > New > Server 선택.
  2. 서버 타입에서 IBM > WebSphere Liberty 선택.
  3. Server's host namelocalhost, Server name은 식별 가능한 이름 입력.
  4. Runtime Environment 설정 단계:
    • 기존 설치된 경우: 'Choose an existing installation' 선택 후 Liberty 설치 경로(wlp 폴더) 지정.
    • 새로 설치할 경우: 'Install from an archive or a repository' 선택 후 원하는 버전 다운로드.
  5. Finish를 클릭하여 설정을 완료합니다.

4. 서버 구동 및 애플리케이션 배포

설정이 완료되면 Eclipse 내에서 서버를 제어할 수 있습니다.

서버 제어

  • Start: Servers 뷰에서 서버 우클릭 > Start (또는 Debug).
  • Console 확인: CWWKF0011I: The server defaultServer is ready to run a smarter planet. 메시지가 뜨면 정상 구동된 것입니다.

프로젝트 배포

  1. Dynamic Web Project 생성.
  2. 프로젝트 우클릭 > Run As > Run on Server.
  3. 등록한 Liberty 서버를 선택하고 Finish.
  4. server.xml에 애플리케이션 구성이 자동으로 추가되며 배포가 진행됩니다.

5. 참고 영상 (Reference Video)

실제 설치 및 구동 과정에 대한 데모 영상입니다.


Next Step:
개발 환경 구축이 완료되었다면, server.xml 파일의 <featureManager> 섹션을 수정하여 필요한 기능(JSP, Servlet, JDBC 등)을 활성화하는 방법을 학습해 보십시오.

Open Stream →
#Linux

[Linux/Java] High CPU 트러블슈팅: OS 스레드와 Java 스레드 매핑 분석 가이드

Java 프로세스(JVM)가 고부하 상태일 때, CPU를 점유하고 있는 범인(특정 스레드)을 찾아내는 방법을 정리합니다. OS 명령어(ps, top)로 문제의 스레드 ID(TID)를 식별하고, 이를 16진수로 변환하여 Java Thread Dump와 매핑하는 과정을 다룹니다.

Test Environment

  • OS: RedHat Linux (CentOS 호환)
  • Target: Java Process (WebSphere/Tomcat 등)

1. 프로세스 및 스레드 식별 (Identify Usage)

먼저 CPU를 많이 사용하는 Java 프로세스의 PID(Process ID)를 찾고, 그 내부에서 실제로 리소스를 소모하는 스레드(LWP, Light Weight Process)를 식별해야 합니다.

전체 프로세스 확인

# Java 프로세스 PID 확인
ps -ef | grep java

스레드별 CPU 점유율 확인 (top)

-H 옵션을 사용하여 프로세스 내부의 스레드 단위로 리소스를 모니터링합니다.

# PID가 12345인 경우
top -H -p 12345

출력 화면에서 PID(실제로는 TID/LWP) 컬럼과 %CPU 컬럼을 확인하여 가장 상단에 있는 번호를 기록합니다.

스레드별 CPU 점유율 확인 (ps)

ps 명령어를 통해서도 스레드 정보를 확인할 수 있습니다. -lmT 옵션이나 -L 옵션을 사용합니다.

# LWP(Light Weight Process) 확인
ps -lmT [PID]

# 또는 커스텀 포맷 사용
ps -eLo pid,lwp,pcpu,comm | grep [PID]

2. 스레드 ID 변환 (Decimal to Hex)

OS에서 확인한 스레드 ID는 10진수(Decimal)이지만, Java Thread Dump 파일(Javacore 등)에서는 스레드 ID가 16진수(Hexadecimal)로 기록됩니다. 따라서 매핑을 위해 변환 과정이 필요합니다.

변환 예시

  • OS TID: 9091 (10진수)
  • Hex TID: 0x2383 (16진수)

변환 명령어

# 쉘에서 바로 변환하기 (예: 9091 -> 2383)
printf '%x\n' 9091

3. 스레드 덤프 생성 및 분석 (Thread Dump)

현재 JVM의 상태를 스냅샷으로 남기기 위해 스레드 덤프를 생성합니다.

덤프 생성 (Kill -3)

kill -3 시그널은 프로세스를 종료하지 않고 표준 출력(stdout)이나 로그 파일로 스레드 정보를 출력합니다.

kill -3 [PID]
  • IBM JDK (WebSphere): javacore.YYYYMMDD.HHMMSS.pid.txt 파일 생성
  • Oracle/Open JDK: catalina.out 또는 지정된 로그 파일에 출력

로그 매핑 분석

생성된 덤프 파일에서 앞서 변환한 16진수 값(예: 0x2383)을 검색합니다. IBM JDK의 경우 nid(Native ID) 또는 native_thread_id 항목과 매칭됩니다.

/* Javacore 예시 */
"WebContainer : 5" (TID:0x12345600, sys_thread_t:0x789abc00, state:R, native ID:0x2383) prio=5
    at com.example.MyClass.infiniteLoop(MyClass.java:45)
    at ...

분석 포인트:

  1. 16진수 ID로 검색하여 해당 스레드를 찾습니다.
  2. 해당 스레드의 상태(Runnable, Waiting 등)를 확인합니다.
  3. Stack Trace를 통해 현재 어떤 코드(메소드)가 실행 중인지 파악하여 병목 지점을 수정합니다.

Next Step:
주기적인 모니터링이 필요하다면 top -Hjstack을 결합한 쉘 스크립트를 작성하여, CPU 임계치 초과 시 자동으로 덤프를 남기도록 자동화해 보십시오.

Open Stream →
#WebSphere

[WebSphere] 디렉토리 리스팅(Directory Listing) 제거 및 보안 설정 (directoryBrowsingEnabled)

웹 서버가 특정 디렉토리 내의 파일 목록을 브라우저에 노출하는 '디렉토리 리스팅' 취약점을 해결하기 위한 WebSphere 설정 가이드입니다. 애플리케이션 레벨(xml) 수정 방식과 관리 콘솔(Admin Console)을 통한 전역 설정 방식을 다룹니다.

0. 배경 및 원인 (Context)

디렉토리 리스팅이 활성화되어 있으면 공격자가 서버의 디렉토리 구조와 파일 목록(백업 파일, 소스 코드 등)을 파악할 수 있어 2차 공격의 빌미가 됩니다.

WebSphere는 정적 파일 처리를 위한 fileServingEnabled 속성과 목록 노출을 위한 directoryBrowsingEnabled 속성을 가지고 있으며, 이를 적절히 제어해야 합니다.

Test Environment

  • OS: CentOS 7.2
  • Web Server: IBM HTTPServer v8.5.0.0
  • WAS: WebSphere Application Server v8.5

1. Method A: 애플리케이션 설정 파일 수정

개별 애플리케이션 단위로 설정을 적용할 때 사용합니다. WAR/EAR 파일 내부의 IBM 확장 설정 파일을 직접 수정합니다.

설정 파일 대상

  • WAS v7.0 이상: ibm-web-ext.xml
  • WAS v6.1 이하: ibm-web-ext.xmi (Legacy)

설정 내용 (ibm-web-ext.xml)

enable-directory-browsing 속성을 false로 명시합니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-ext
    xmlns="http://websphere.ibm.com/xml/ns/javaee/web-ext/1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee/web-ext/1.0 http://websphere.ibm.com/xml/ns/javaee/web-ext/1.0/web-ext.xsd">

    <!-- 정적 파일 서빙 활성화 (이미지, HTML 등) -->
    <enable-file-serving value="true"/>
    
    <!-- 핵심: 디렉토리 리스팅 비활성화 -->
    <enable-directory-browsing value="false"/>

</web-ext>

2. Method B: 웹 컨테이너(Web Container) 전역 설정

WAS 관리 콘솔에서 서버 단위로 속성을 추가하여 제어하는 방식입니다. 애플리케이션을 재배포하지 않고 설정을 변경할 수 있어 운영 환경에서 선호됩니다.

설정 경로

서버(Servers) > 서버 유형(Server Types) > WebSphere application servers > [서버명] > 웹 컨테이너 설정(Web Container Settings) > 웹 컨테이너(Web container) > 사용자 정의 특성(Custom properties)

주요 속성 값

아래 속성을 새로 작성(New)하여 추가합니다.

이름 (Name) 값 (Value) 설명
directoryBrowsingEnabled false 디렉토리 목록 조회 기능을 비활성화합니다. (보안 필수)
fileServingEnabled true WAS가 정적 파일(html, img 등)을 처리할지 여부입니다. (false 설정 시 정적 파일 처리가 불가할 수 있음)
참고: fileServingEnabledfalse로 설정하면 디렉토리 리스팅도 차단되지만, WAS가 이미지나 CSS 같은 정적 리소스를 전혀 제공하지 않게 되므로 주의가 필요합니다. 일반적으로는 directoryBrowsingEnabledfalse로 설정합니다.

3. 검증 (Verification)

  1. 설정 적용 후 WAS 인스턴스를 재기동합니다.
  2. 브라우저에서 index.html이 없는 디렉토리 경로(예: http://domain/images/)로 접속합니다.
  3. 403 Forbidden 에러가 발생하면 보안 설정이 정상적으로 적용된 것입니다.
Open Stream →
#Liberty

[WebSphere] Liberty Core 설치 및 필수 설정 가이드 (CLI Install, server.xml, Plugin)

IBM WebSphere Liberty Core를 GUI 없이 Command Line(CLI) 환경에서 설치하고, 서버 생성 및 기동, 핵심 설정(server.xml, JVM), 그리고 웹 서버 연동을 위한 플러그인 생성(pluginUtility) 과정을 단계별로 정리합니다.

1. 제품 설치 (CLI Mode)

Liberty는 Installation Manager(IM)의 imcl 명령어를 통해 설치합니다. GUI를 사용할 수 없는 리눅스/유닉스 서버 환경에서 필수적인 방법입니다.

설치 명령어 (imcl)

-repositories 옵션에는 설치 파일(Repository)의 경로를 지정합니다. 콤마(,)로 구분하여 WAS와 JDK 리포지토리를 동시에 지정할 수 있습니다.

# 설치 예시 (Windows 기준, Linux는 경로만 변경)
imcl install com.ibm.websphere.liberty.v85_8.5.16002.20160526_2338 \
com.ibm.websphere.liberty.IBMJAVA.v80_8.0.3020.20161124_1304 \
-repositories "D:\Liberty\16.0.0.2-WS-LIBERTY-CORE,D:\work_file\was_install\v8.5.5\SDK\8.0.3.20" \
-installationDirectory "F:\app\IBM\wlpcore\AppServer" \
-acceptLicense \
-showProgress -sP
Tip: 패키지 ID(com.ibm...)를 모를 경우 imcl listAvailablePackages -repositories [경로] 명령어로 미리 확인해야 합니다.

2. 서버 생명주기 관리 (Server Lifecycle)

설치가 완료되면 bin 디렉토리의 server 스크립트를 사용하여 서버 인스턴스를 생성하고 제어합니다.

1) 서버 생성 (Create)

cd [WLP_HOME]/bin
# 구문: server create [서버명]
server.bat create test01

생성이 완료되면 [WLP_HOME]/usr/servers/test01 경로에 설정 파일들이 만들어집니다.

2) 서버 기동 및 상태 확인 (Start/Status)

# 서버 기동
server.bat start test01

# 상태 확인 (필수 검증 단계)
server.bat status test01

3. 핵심 설정 (server.xml)

Liberty의 모든 구성은 server.xml 파일 하나에 통합되어 있습니다. 필요한 기능(Feature)만 선언해서 사용하는 구조입니다.

설정 파일 위치

  • [WLP_HOME]/usr/servers/[서버명]/server.xml

주요 설정 예시

<?xml version="1.0" encoding="UTF-8"?>
<server description="Test Server">

    <!-- 1. Feature Manager: 필요한 기능 모듈 로드 -->
    <featureManager>
        <feature>jsp-2.2</feature>
        <feature>jdbc-4.0</feature>
        <feature>localConnector-1.0</feature> <!-- 로컬 관리용 -->
        <feature>adminCenter-1.0</feature>    <!-- 웹 관리 콘솔 -->
    </featureManager>

    <!-- 2. HTTP Endpoint: 포트 설정 -->
    <!-- host="*"는 모든 IP 대역에서의 접속을 허용함 -->
    <httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="9080" httpsPort="9443">
        <tcpOptions soReuseAddr="true" />
    </httpEndpoint>

    <!-- 3. Web Server Plugin 설정 -->
    <pluginConfiguration webserverPort="80" webserverSecurePort="443"/>

    <!-- 4. Application 배포 설정 (자동 인식이 편함) -->
    <applicationManager autoExpand="true"/>
    
    <!-- 5. DB Connection (Oracle 예시) -->
    <dataSource id="WorklightDS" jndiName="jdbc/WorklightDS">
        <jdbcDriver libraryRef="OracleLib"/>
        <properties.oracle 
            driverType="thin" 
            databaseName="ORCL" 
            serverName="localhost" 
            portNumber="1521" 
            user="SCOTT" 
            password="{xor}KDAtNDM2ODcr"/> <!-- securityUtility로 암호화 권장 -->
    </dataSource>

    <!-- 6. Logging 설정 -->
    <logging maxFiles="5" consoleLogLevel="INFO"/>

</server>
초보자를 위한 Tip:
설정 파일의 password="{xor}..." 부분은 평문을 그대로 넣지 않고, Liberty가 제공하는 bin/securityUtility encode [암호] 명령어를 사용하여 인코딩된 값을 넣어야 보안상 안전합니다.

4. 환경 변수 및 JVM 옵션 설정

메모리(Heap) 설정이나 로그 경로 변경 등은 별도의 설정 파일에서 관리합니다.

1) JVM 옵션 (jvm.options)

Heap Size나 GC 로그 설정은 jvm.options 파일에 라인 단위로 작성합니다.

  • 위치: [WLP_HOME]/usr/servers/[서버명]/jvm.options
# Heap Memory 설정
-Xms512m
-Xmx1024m

# GC 로그 설정
-verbose:gc
-Xverbosegclog:verbosegc.log
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC

2) 환경 변수 (server.env)

JAVA_HOME 지정이나 커스텀 로그 경로는 server.env에 정의합니다.

# Java 버전 지정
JAVA_HOME=C:\Java\jdk1.8.0

# 로그 경로 변경 (Optional)
WLP_OUTPUT_DIR=F:\app\IBM\wlpcore\AppServer\usr\logs\test02

5. 웹 서버 플러그인 (Plugin) 생성

Liberty 서버 앞단에 IHS(Apache)를 둔다면, plugin-cfg.xml을 생성하여 웹 서버에 알려주어야 합니다.

플러그인 생성 도구 (pluginUtility)

Liberty 16.0.0.4 버전부터 pluginUtility 명령어를 사용합니다.

cd [WLP_HOME]/bin

# 1. 로컬 서버용 플러그인 생성
pluginUtility generate --server=test01 --targetpath=./plugin-cfg.xml

# 2. 원격 서버용 플러그인 생성 (Admin Center 기능 필요)
pluginUtility generate --server=admin:password@remoteHost:9443 --targetpath=./plugin-cfg.xml

# 3. 여러 플러그인 병합 (Merge)
pluginUtility merge --sourcepath=../usr/plugin --targetpath=../usr/merged_plugin.xml

웹 서버(httpd.conf) 적용

생성된 xml 파일을 웹 서버로 복사한 후 httpd.conf에 등록합니다.

# Windows 예시
LoadModule was_ap22_module "C:\IBM\HTTPServer\plugins\bin\mod_was_ap22_http.dll"
WebSpherePluginConfig "C:\IBM\HTTPServer\plugins\config\webserver1\plugin-cfg.xml"

# Linux/Unix 예시
LoadModule was_ap22_module "/opt/IBM/HTTPServer/plugins/bin/mod_was_ap22_http.so"
WebSpherePluginConfig "/opt/IBM/HTTPServer/plugins/config/webserver1/plugin-cfg.xml"

Next Step:
기본 설치와 설정이 끝났다면, adminCenter 기능을 활성화하고 브라우저(https://localhost:9443/adminCenter)로 접속하여 GUI 환경에서 서버 상태를 모니터링해 보십시오.

Open Stream →