#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 →
#AIX

[Linux/AIX] 윈도우 파일 업로드 시 발생하는 개행 문자(^M) 제거 방법 (Perl, vi, sed)

Windows(CRLF)에서 작성한 파일을 Unix/Linux(LF) 계열 서버로 업로드하면, 라인 끝에 ^M 특수문자가 붙어 스크립트 실행 에러(bad interpreter)를 유발합니다. AIX 환경에서도 확실하게 동작하는 Perl 명령어를 이용한 일괄 제거 방법을 정리합니다.

0. 원인 및 증상 (Context)

운영체제마다 줄바꿈(New Line)을 처리하는 방식이 다릅니다.

  • Windows: CR(Carriage Return, \r) + LF(Line Feed, \n)
  • Unix/Linux/AIX: LF(\n)

FTP 전송 시 ASCII 모드가 아닌 Binary 모드로 전송하거나, 단순 복사/붙여넣기를 할 경우 Windows의 CR(\r) 문자가 그대로 남아 vi 에디터에서 ^M으로 표시됩니다.

Test Environment

  • OS: AIX (또는 Linux)
  • Shell: sh, ksh, bash

1. 문제 확인 (Issue Identification)

쉘 스크립트 실행 시 에러가 발생하거나, vi로 파일을 열었을 때 라인 끝마다 ^M이 붙어있는 것을 확인할 수 있습니다.

vi 에디터 화면

#!/bin/sh^M
#./startServer.sh server_name^M
#./stopServer.sh server_name -username username -password password^M

2. 해결 방법 A: Perl 명령어 사용 (권장)

AIX의 기본 sed 명령어는 -i(파일 직접 수정) 옵션을 지원하지 않는 경우가 많습니다. 따라서 Perl을 사용하는 것이 가장 호환성이 좋고 간편합니다.

명령어 구문

^M을 직접 입력하기 번거로우므로, 8진수 코드인 \015를 사용하는 것이 안전합니다.

# 구문: perl -pi -e 's/찾을문자/바꿀문자/g' [파일명]
perl -pi -e 's/\015//g' stopWasAll.sh

다중 파일 일괄 처리

와일드카드(*)를 사용하여 여러 파일을 한 번에 변환할 수 있습니다.

# 현재 경로의 모든 .sh 파일에서 CR 제거
perl -pi -e 's/\015//g' *.sh

3. 해결 방법 B: vi 에디터 내부 치환

파일을 열어놓은 상태에서 수정하고 싶을 때 사용합니다.

  1. vi로 파일 열기
  2. 명령 모드(ESC)에서 치환 명령어 입력
:%s/^M//g
Tip: 위 명령어의 ^MShift + 6, M을 타이핑하는 것이 아닙니다.
반드시 Ctrl + V를 누른 상태에서 Ctrl + M을 눌러야 입력됩니다.

4. 해결 방법 C: dos2unix 유틸리티

리눅스(CentOS/Ubuntu) 환경이라면 전용 도구를 설치하여 해결하는 것이 가장 쉽습니다.

# 설치 (CentOS)
yum install -y dos2unix

# 변환
dos2unix stopWasAll.sh

5. 검증 (Verification)

변환 후 다시 vi로 파일을 열어 ^M 문자가 사라졌는지 확인합니다.

test1 root [/was8/bin]# vi stopWasAll.sh

#!/bin/sh
#./startServer.sh server_name
#./stopServer.sh server_name -username username -password password
#PropFilePasswordEncoder.sh
#export LANG=en_us.utf8

깔끔하게 정리된 것을 확인할 수 있습니다.

Open Stream →
#apache

[Apache] CentOS 7 소스 컴파일 설치 완벽 가이드: 의존성(APR, PCRE, OpenSSL) 포함

CentOS 7 환경에서 Apache HTTP Server 2.4를 소스 코드로 컴파일하여 설치하는 전체 과정을 다룹니다. APR, APR-Util, PCRE, OpenSSL 등 필수 의존성 패키지를 별도 경로(Custom Path)에 설치하고 이를 Apache와 연동하는 방법을 중점적으로 설명합니다.

0. 사전 준비 (Prerequisites)

소스 컴파일을 위해 필요한 C 컴파일러와 기본 라이브러리를 설치합니다.

OS 및 컴파일 도구 확인

  • OS: CentOS 7 (Kernel 3.10.0)
  • 패키지 설치: yum -y install gcc make gcc-c++ pcre-devel expat-devel

1. 의존성 라이브러리 설치 (Dependencies)

Apache 2.4 구동에 필요한 라이브러리들을 /SW/web/tools 하위에 격리하여 설치합니다. 이는 시스템 라이브러리와의 충돌을 방지하기 위함입니다.

1) APR (Apache Portable Runtime)

OS 간의 차이를 추상화해 주는 핵심 라이브러리입니다.

# 다운로드 및 압축 해제 후 이동
./configure --prefix=/SW/web/tools/apr
make && make install

2) APR-Util

APR의 유틸리티 확장판이며, 반드시 APR이 먼저 설치되어 있어야 합니다.

# --with-apr 옵션으로 위에서 설치한 경로 지정 필수
./configure --prefix=/SW/web/tools/apr-util --with-apr=/SW/web/tools/apr
make && make install

3) PCRE (Perl Compatible Regular Expressions)

URL 재작성(Rewrite) 모듈 등 정규 표현식 처리에 사용됩니다.

./configure --prefix=/SW/web/tools/pcre
make && make install

4) OpenSSL (HTTPS 지원)

보안 통신(SSL/TLS)을 위해 OpenSSL 소스를 컴파일합니다.

# config 명령어로 경로 설정
./config --prefix=/SW/web/tools/openssl --openssldir=/SW/web/tools/openssl

make && make install

2. Apache (HTTPD) 컴파일 및 설치

모든 의존성이 준비되었으므로 Apache를 컴파일합니다. configure 단계에서 앞서 설치한 라이브러리들의 경로를 정확히 지정하는 것이 핵심입니다.

Configure 실행

tar -zxvf httpd-2.4.41.tar.gz
cd httpd-2.4.41

# 설정 (한 줄로 입력)
./configure \
--prefix=/SW/web/httpd24 \
--enable-so \
--enable-rewrite \
--enable-proxy \
--enable-ssl \
--enable-mods-shared=all \
--enable-modules=shared \
--enable-mpms-shared=all \
--with-mpm=worker \
--with-apr=/SW/web/tools/apr \
--with-apr-util=/SW/web/tools/apr-util \
--with-pcre=/SW/web/tools/pcre \
--with-ssl=/SW/web/tools/openssl \
--enable-unique-id

주요 옵션 설명

  • --enable-so: DSO(Dynamic Shared Object) 모듈 적재 기능 활성화 (필수)
  • --enable-mods-shared=all: 모든 모듈을 동적 모듈로 컴파일
  • --with-mpm=worker: 멀티 프로세스 모듈(MPM)을 Worker 방식으로 지정 (성능 유리)
  • --with-[lib]: 앞서 설치한 의존성 라이브러리 경로 연결

컴파일 및 설치

make && make install

3. 구동 및 검증 (Verification)

설치가 완료되면 서비스를 기동하고 브라우저 접속을 테스트합니다.

서비스 기동

# Apache 컨트롤러 실행
/SW/web/httpd24/bin/apachectl start

# 프로세스 확인
ps -ef | grep httpd
netstat -anotp | grep :80

방화벽 설정 (CentOS 7)

프로세스가 떠 있어도 방화벽이 막혀있으면 접속이 안 됩니다. 80 포트를 열어줍니다.

firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --reload

접속 확인

브라우저 주소창에 서버 IP를 입력하여 "It works!" 페이지가 뜨는지 확인합니다.

Apache It Works Page

[그림] 설치 성공 시 확인 가능한 기본 페이지


Next Step:
기본 설치가 완료되었습니다. 이제 운영 환경에 맞춰 httpd.conf에서 ServerName 경고를 해결하고, httpd-mpm.conf에서 Worker 프로세스 튜닝을 진행해 보십시오.

Open Stream →
#command

[Linux] find 명령어 실무 패턴 3가지: 파일명, 수정 시간, 문자열 검색(grep) 활용

리눅스(CentOS 7) 환경에서 원하는 파일을 빠르고 정확하게 찾기 위한 find 명령어의 필수 옵션을 정리합니다. 대소문자 구분 없는 검색, 최근 변경된 파일 탐색, 그리고 xargs를 조합한 파일 내용 검색 방법을 다룹니다.

Test Environment

  • OS: CentOS 7 (3.10.0-957.el7.x86_64)
  • Shell: Bash

1. 파일명으로 검색 (By Name)

가장 기본적인 사용법입니다. -name 옵션은 정확한 이름을, -iname 옵션은 대소문자를 무시하고 검색합니다.

기본 검색

# 전체 경로(/)에서 Mem.sh 파일 찾기
find /sw -name "Mem.sh"

# 현재 디렉토리(.)에서 찾기
find . -name "Mem.sh"

대소문자 무시 검색 (Insensitive)

파일명의 대소문자가 확실하지 않을 때 유용합니다.

# Mem.sh, MEM.sh 모두 검색됨
find /sw -iname "Mem.sh"
Tip (에러 숨기기):
검색 도중 Permission denied 메시지가 너무 많이 뜬다면 명령어 뒤에 2>/dev/null을 붙여 에러 메시지를 버릴 수 있습니다.
예: find / -name "test" 2>/dev/null

2. 수정 시간으로 검색 (By Time)

장애 발생 시점이나 로그 분석 시, 특정 시간 내에 변경된 파일을 찾을 때 -mtime(Modification Time) 옵션을 사용합니다.

사용 예시

# 최근 1일(24시간) 이내에 수정된 .sh 파일 검색
find /sw -name "*.sh" -mtime -1

옵션 상세 설명

  • -mtime -n: 최근 n일 이내에 변경됨 (Today)
  • -mtime +n: n일 이전에 변경됨 (Old files)
  • -mtime n: 정확히 n일 전에 변경됨

3. 파일 내용 문자열 검색 (With Grep)

find로 찾은 파일들의 내용(Content)을 검색하고 싶을 때, 파이프(|)와 xargs를 사용하여 grep으로 넘겨줍니다.

검색 파이프라인

[파일 찾기][목록 전달][내용 검색]의 흐름입니다.

# 1일 이내 수정된 sh 파일들 중에서 "Mem"이라는 글자가 포함된 라인 출력
find /sw -name "*.sh" -mtime -1 | xargs grep "Mem"

실행 결과 해석

/sw/Mem.sh:MEMINFO=`cat /proc/meminfo...`  <-- 파일명:내용
/sw/Mem1.sh: TOTAL=`free | grep ^Mem...`
/sw/Mem1.sh: USED=`free | grep ^Mem...`

grepfind가 찾아낸 파일들을 하나씩 열어서 "Mem" 키워드가 있는지 확인하고, 해당 라인을 파일명과 함께 출력해 줍니다.


Next Step:
파일을 단순히 찾는 것을 넘어, -exec 옵션을 사용하여 검색된 파일의 권한을 일괄 변경(chmod)하거나 삭제(rm)하는 등의 고급 활용법을 익혀보세요.

Open Stream →
#command

[Linux] 파일/디렉토리 소유권(Owner/Group) 변경: chown 명령어 사용법 및 주의사항

리눅스 환경(CentOS 7)에서 파일 및 디렉토리의 소유자(User)와 그룹(Group)을 변경하는 chown 명령어 사용법을 정리합니다. 하위 경로까지 일괄 변경하는 -R 옵션과 실무 예제를 다룹니다.

0. 배경 지식 (Context)

리눅스의 모든 파일은 특정 사용자와 그룹에 속하게 됩니다. 보통 root 권한으로 설치하거나 복사한 파일은 소유권이 root로 되어 있어, 일반 애플리케이션 계정(예: wasadm, tomcat 등)에서 접근하거나 실행할 때 "Permission denied" 오류가 발생합니다. 이때 chown을 사용하여 소유권을 적절한 계정으로 넘겨주어야 합니다.

Test Environment

  • OS: CentOS 7 (3.10.0-957.el7.x86_64)
  • User: root (명령어 실행 주체), wasadm (대상 계정)

1. 기본 문법 (Syntax)

chown(Change Owner) 명령어의 기본 구조입니다. 루트(Superuser) 권한이 필요합니다.

# 소유자만 변경
chown [USER] [FILE]

# 소유자와 그룹 동시 변경 (가장 많이 사용)
chown [USER]:[GROUP] [FILE]

# 하위 디렉토리까지 재귀적 변경
chown -R [USER]:[GROUP] [DIRECTORY]

2. 실무 사용 예시 (Examples)

제공해주신 로그를 바탕으로 상황별 명령어 사용법을 분석합니다.

Step 1: 전체 초기화 (root 권한으로 설정)

-R 옵션을 사용하여 현재 디렉토리(*)의 모든 파일과 폴더를 root:root 소유로 변경합니다.

[root@localhost sw]# chown -R root:root *

# 확인
[root@localhost sw]# ls -alrt
drwxrwxrwx.  2 root root   6 Feb  5 01:49 img
drwx------.  2 root root   6 Feb  5 01:49 was
...
주의 (Warning):
chown -R은 매우 강력한 명령어입니다. 실수로 루트 디렉토리(/)나 시스템 디렉토리에서 실행할 경우 시스템 부팅이 불가능해질 수 있으므로, 실행 전 현재 경로(pwd)를 반드시 확인하십시오.

Step 2: 특정 서비스 계정으로 이관

WAS나 웹 서버 운영을 위해 특정 디렉토리(img, was)와 스크립트(Mem.sh)의 소유권을 wasadm 계정으로 변경합니다.

# 디렉토리 및 파일 소유권 변경 (wasadm 계정, wasadm 그룹)
[root@localhost sw]# chown wasadm:wasadm img
[root@localhost sw]# chown wasadm:wasadm was
[root@localhost sw]# chown wasadm:wasadm Mem.sh

Step 3: 변경 결과 검증 (Verification)

ls -l 명령어로 변경된 소유권을 확인합니다. 3번째 컬럼(Owner)과 4번째 컬럼(Group)이 변경된 것을 볼 수 있습니다.

[root@localhost sw]# ls -alrt
total 8
# 변경된 항목 (wasadm)
drwxrwxrwx.  2 wasadm wasadm   6 Feb  5 01:49 img
drwx------.  2 wasadm wasadm   6 Feb  5 01:49 was
-rwxr-xr-x.  1 wasadm wasadm 428 Feb  8 01:16 Mem.sh

# 변경되지 않은 항목 (root 유지)
drwx------.  2 root   root     6 Feb  5 01:49 web
drwxr-xr-x.  2 root   root     6 Feb  5 01:49 bin
...

Next Step:
소유권 변경이 완료되었다면, 해당 사용자가 파일에 대해 어떤 작업을 할 수 있는지 결정하는 권한(Permission) 설정(chmod) 단계로 넘어가야 합니다.

Open Stream →
#command

[Linux] CentOS 7 메모리 사용률 분석 완벽 가이드: free 명령어 변화와 실질 사용량 계산

CentOS 7(RHEL 7)부터 free 명령어의 출력 형식이 변경되었습니다. 기존의 buffers/cache 라인이 사라지고 available 컬럼이 추가된 배경을 이해하고, 정확한 메모리 사용률을 계산하는 방법을 정리합니다.

0. 배경 지식: CentOS 6 vs 7 차이점

리눅스는 남는 메모리를 적극적으로 캐시(Cache)로 사용하여 성능을 높입니다. 따라서 'Used'가 높다고 해서 반드시 메모리가 부족한 것은 아닙니다.

  • CentOS 6 이하: -/+ buffers/cache 행을 통해 실질 사용량을 확인했습니다.
  • CentOS 7 이상: 커널이 직접 계산한 available 컬럼을 통해 "즉시 사용 가능한 메모리"를 판단합니다.

Test Environment

  • OS: CentOS 7 (Kernel 3.10.0-957.el7.x86_64)

1. 메모리 확인 명령어 (free)

가장 기본적인 확인 방법입니다. -m 옵션은 Megabyte 단위로 출력합니다.

[root@localhost sw]# free -m
              total        used        free      shared  buff/cache   available
Mem:           7803         892        4686         263        2224        6277
Swap:          8064           0        8064

실시간 모니터링 및 상세 보기

-w(wide) 옵션을 주면 buffer와 cache를 분리해서 볼 수 있고, -s(seconds) 옵션으로 반복 조회가 가능합니다.

# 1초 간격으로 buffer/cache를 분리하여 출력
free -mw -s 1

2. 메모리 사용률 계산 공식 (Calculation)

단순히 used / total로 계산하면 캐시 메모리까지 사용량에 포함되어 수치가 과도하게 높게 나옵니다. 목적에 따라 계산 방식을 달리해야 합니다.

공식 A: OS 관점의 사용률 (캐시 포함)

메모리가 실제로 얼마나 할당되어 있는지(반납되지 않은 상태) 확인할 때 사용합니다.

$$ Usage(\%) = \frac{used}{total} \times 100 $$

공식 B: 애플리케이션 관점의 실질 사용률 (권장)

"실제로 메모리가 부족한가?"를 판단할 때는 available 값을 기준으로 해야 합니다.

$$ Usage(\%) = \frac{total - available}{total} \times 100 $$

Tip: sar -r 1 명령어를 통해서도 %memused(메모리 사용률)를 확인할 수 있습니다.

3. 주요 파라미터 설명 (Parameters)

CentOS 7 free 명령어의 각 컬럼이 의미하는 바는 다음과 같습니다.

파라미터 설명
total 설치된 전체 물리 메모리 크기
used 현재 할당되어 사용 중인 메모리 (total - free - buff/cache)
free 아무 용도로도 사용되지 않는 완전한 유휴 메모리
shared tmpfs(램디스크) 등 프로세스 간 공유되는 메모리
buff/cache 커널 버퍼 및 파일 시스템 캐시 (필요시 즉시 반환 가능)
available (핵심) 스와핑(Swapping) 없이 새로운 프로세스 실행에 즉시 할당 가능한 메모리 추정치

Next Step:
메모리 사용률이 비정상적으로 높다면(available 부족), top 명령어로 메모리 누수(Leak)가 의심되는 프로세스를 찾거나, echo 3 > /proc/sys/vm/drop_caches 명령어로 캐시를 강제 반환하여 가용 공간을 확보하는 방법을 검토해 보세요.

Open Stream →
#command

[Linux] Java 실제 설치 경로 확인 방법: which vs readlink 차이점 및 JAVA_HOME 설정

리눅스 환경에서 java 명령어의 실제 설치 위치(Absolute Path)를 찾는 방법을 정리합니다. 단순 경로 확인용인 which와 심볼릭 링크의 원본을 찾아주는 readlink -f의 차이점을 이해하고, 이를 통해 JAVA_HOME을 설정하는 팁을 다룹니다.

0. 배경 지식 (Context)

리눅스(특히 CentOS/RHEL 계열)는 alternatives 시스템을 사용하여 여러 버전의 프로그램을 관리합니다. 때문에 /usr/bin/java는 실제 실행 파일이 아니라, 여러 단계의 바로가기(Symbolic Link)로 연결된 껍데기일 확률이 높습니다.

Test Environment

  • OS: CentOS 7 (3.10.0-957.el7.x86_64)
  • Package: OpenJDK 1.8

1. 명령어 경로 확인 (which)

가장 기본적으로 사용하는 명령어입니다. 환경 변수 $PATH에 등록된 경로 중 어디에 있는 명령어가 실행되는지 알려줍니다.

[wasadm@localhost ~]$ which java
/usr/bin/java
한계점: 위 결과인 /usr/bin/java는 실제 파일이 아닌 심볼릭 링크일 가능성이 높아서, 이 경로를 JAVA_HOME으로 설정하면 오류가 발생합니다.

2. 원본 경로 추적 (readlink -f)

심볼릭 링크가 아무리 여러 단계로 꼬여 있어도, 최종 원본 파일의 절대 경로를 한 번에 찾아주는 가장 확실한 명령어입니다.

# 구문: readlink -f [심볼릭_링크_경로]
[wasadm@localhost ~]$ readlink -f /usr/bin/java

# 출력 결과 (실제 설치 위치)
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre/bin/java

위 결과에서 마지막 /bin/java를 제외한 앞부분이 바로 JAVA_HOME이 됩니다.


3. 링크 구조 단계별 확인 (ls -l)

readlink가 어떻게 동작하는지 ls -l 명령어로 한 단계씩 추적해보면 리눅스의 alternatives 구조를 이해할 수 있습니다.

Step 1: 실행 파일 확인

[wasadm@localhost ~]$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 Feb  5 01:36 /usr/bin/java -> /etc/alternatives/java

/usr/bin/java/etc/alternatives/java를 가리키고 있습니다.

Step 2: alternatives 확인

[wasadm@localhost ~]$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 71 Feb  5 01:36 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre/bin/java

/etc/alternatives/java가 비로소 실제 JDK가 설치된 경로를 가리키고 있습니다. readlink -f는 이 과정을 한 번에 수행해 줍니다.


4. 활용: JAVA_HOME 환경 변수 설정

위에서 찾은 경로를 활용하여 환경 변수를 등록합니다. (/etc/profile 또는 ~/.bash_profile)

# 원본 경로: /usr/lib/jvm/java-1.8.0-.../jre/bin/java
# bin/java 앞부분까지만 복사

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre
export PATH=$JAVA_HOME/bin:$PATH

Next Step:
만약 서버에 여러 버전의 Java가 설치되어 있어 기본 실행 버전을 변경하고 싶다면, alternatives --config java 명령어를 사용하여 간편하게 스위칭할 수 있습니다.

Open Stream →
#command

[Linux] 파일/디렉토리 권한 관리 완벽 가이드: chmod 명령어와 755, 777의 의미

리눅스 환경(CentOS 7)에서 파일 및 디렉토리의 접근 권한을 제어하는 chmod 명령어 사용법을 정리합니다. 숫자 모드(755, 644)와 문자열 모드(u+x)의 차이를 이해하고, -R 옵션을 통해 하위 경로까지 일괄 적용하는 실무 예제를 다룹니다.

0. 배경 지식: 권한의 구조 (Permission Structure)

리눅스의 파일 권한은 소유자(User), 그룹(Group), 기타(Other) 세 가지 대상에 대해 읽기(r), 쓰기(w), 실행(x) 권한을 부여하는 구조입니다.

권한 확인 (ls -l)

ls -l
# 결과 예시: drwxr-xr-x (755)
# d(디렉토리) | rwx(소유자) | r-x(그룹) | r-x(기타)

1. 권한 변경 (chmod)

chmod(Change Mode) 명령어를 사용하여 파일이나 디렉토리의 권한을 변경합니다. 이미 생성된 파일의 현재 상태를 변경하는 명령어입니다.

옵션 설명

  • -R (--recursive): 디렉토리 내부의 모든 파일과 하위 디렉토리까지 재귀적으로(일괄) 변경합니다. (가장 많이 사용)

실무 사용 예시

# 1. WAS 디렉토리: 소유자만 모든 권한(7), 나머지는 접근 불가(0)
chmod -R 700 ./was

# 2. 웹 루트 및 바이너리: 소유자(7), 그룹/기타는 읽기/실행만(5) - 일반적인 설정
chmod -R 755 ./web
chmod -R 755 ./bin

# 3. 이미지 업로드 폴더: 누구나 쓰고 읽기 가능 (보안 주의!)
chmod -R 777 ./img

2. 권한 설정 방식 A: 숫자 모드 (Octal Mode)

가장 직관적이고 많이 사용되는 방식입니다. 각 권한에 할당된 점수(4, 2, 1)를 더해서 표현합니다.

권한 (Permission) 기호 (Symbol) 숫자 값 (Octal)
Read (읽기) r 4
Write (쓰기) w 2
Execute (실행) x 1

조합 예시

  • 7 (rwx): 4 + 2 + 1 (모든 권한)
  • 6 (rw-): 4 + 2 (읽기/쓰기 - 일반 파일)
  • 5 (r-x): 4 + 1 (읽기/실행 - 실행 파일, 디렉토리)
  • 0 (---): 권한 없음

3. 권한 설정 방식 B: 문자열 모드 (Symbolic Mode)

특정 대상의 권한만 콕 집어서 추가(+)하거나 제거(-)할 때 유용합니다.

대상 (Who) 연산자 (Op) 권한 (Permission)
u: User (소유자)
g: Group (그룹)
o: Other (기타)
a: All (전체, ugo)
+: 추가
-: 제거
=: 지정
r: 읽기
w: 쓰기
x: 실행

사용 예시

# run.sh 파일에 실행(x) 권한 추가 (모든 사용자에게)
chmod +x run.sh

# 그룹(g)에게 쓰기(w) 권한 제거
chmod g-w file.txt

# 기타 사용자(o)에게 읽기(r) 권한만 할당
chmod o=r file.txt

Next Step:
파일의 권한뿐만 아니라 소유권을 변경해야 할 때는 chown(Change Owner) 명령어를 사용해야 합니다. chown user:group filename 형식을 함께 익혀두세요.

Open Stream →
#EAP7

[JBoss EAP 7] Datasource 패스워드 암호화 가이드: Picketbox Security Domain 설정

보안 컴플라이언스 준수를 위해 JBoss EAP 7의 standalone.xml 또는 domain.xml 파일 내에 저장되는 DB 패스워드를 암호화하는 방법을 정리합니다. org.picketbox 모듈을 이용하여 암호화된 문자열을 생성하고, Security Domain을 통해 데이터소스와 연동합니다.

0. 배경 및 준비 (Context)

JBoss 설정 파일에 비밀번호를 평문으로 저장하면 보안 감사 시 지적 대상이 됩니다. 이를 해결하기 위해 JBoss는 Security Domain을 통해 인증 과정을 위임하는 방식을 제공합니다.

Test Environment

  • OS: CentOS 7.2
  • WAS: JBoss EAP 7.2
  • JDK: 1.8

1. 비밀번호 암호화 문자열 생성 (Encryption)

가장 먼저 실제 DB 패스워드를 암호화된 문자열로 변환해야 합니다. JBoss 내부 모듈인 picketbox를 Java로 실행하여 변환합니다.

암호화 스크립트 (create_encrypt_pw.sh)

JBoss 패치(CP)가 적용되면 .overlays 디렉토리에 라이브러리가 변경될 수 있습니다. 아래 스크립트는 패치 여부를 자동으로 감지하여 적절한 jar 파일을 찾아 실행합니다.

#!/bin/sh

# 1. 환경 변수 설정 (사용자 환경에 맞게 수정 필수)
export JAVA_HOME="/SW/was/java1.8"
export PATH="$JAVA_HOME/bin:$PATH"
JBOSS_HOME="/SW/was/JBoss7.2"

# 2. 라이브러리 경로 탐색 (Overlay 지원)
OVERLAY_DIRECTORY="$JBOSS_HOME/modules/system/layers/base/.overlays"
SEARCH_DIRECTORY="$JBOSS_HOME/modules/system/layers/base/org/picketbox/main"

if [ -d "$OVERLAY_DIRECTORY" ]; then
    # 최신 패치 디렉토리 확인
    PATCH_SUBDIRECTORY=$(ls -dt $OVERLAY_DIRECTORY/* | grep "CP" | head -n 1)
    if [ -n "$PATCH_SUBDIRECTORY" ]; then
        echo "Info: Patch directory detected: $PATCH_SUBDIRECTORY"
        SEARCH_DIRECTORY="$PATCH_SUBDIRECTORY/org/picketbox/main"
    fi
fi

# 3. Classpath 설정
export CLASSPATH=$(find "$SEARCH_DIRECTORY" -name "*.jar" -print | tr '\n' ':')$CLASSPATH

# 4. 암호화 실행
echo ""
read -p "Enter Database Password : " PASSWORD
echo ""
echo "####################################################"
java org.picketbox.datasource.security.SecureIdentityLoginModule "$PASSWORD"
echo "####################################################"
echo ""

실행 결과 예시

Encoded password: 9fdd42c2a7390d3

출력된 Encoded password 값을 복사해 둡니다.


2. Security Domain 설정 (standalone.xml)

생성한 암호화 패스워드를 사용하는 보안 도메인을 정의합니다. security 서브시스템 내에 작성합니다.

설정 내용

<subsystem xmlns="urn:jboss:domain:security:2.0">
    <security-domains>
        
        <security-domain name="encryptedSecurityDB" cache-type="default">
            <authentication>
                <login-module code="org.picketbox.datasource.security.SecureIdentityLoginModule" flag="required">
                    <module-option name="username" value="sa"/>
                    <module-option name="password" value="9fdd42c2a7390d3"/> <!-- 암호화된 값 -->
                    <module-option name="managedConnectionFactoryName" value="jboss.jca:service=LocalTxCM"/>
                </login-module>
            </authentication>
        </security-domain>
        
    </security-domains>
</subsystem>
옵션 설명:
  • username: DB 접속 계정 ID (평문)
  • password: 위에서 생성한 암호화된 패스워드
  • managedConnectionFactoryName: jboss.jca:service=LocalTxCM (고정값 사용)

3. Datasource 연동 설정

이제 데이터소스가 평문 비밀번호 대신 위에서 만든 Security Domain을 바라보도록 수정합니다.

수정 전 (Before)

<datasource ...>
    ...
    <security>
        <user-name>sa</user-name>
        <password>admin1234</password>
    </security>
</datasource>

수정 후 (After)

user-namepassword 태그를 삭제하고 security-domain 태그를 추가합니다.

<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
    <driver>h2</driver>
    
    <security>
        <security-domain>encryptedSecurityDB</security-domain>
    </security>
</datasource>

4. 검증 (Verification)

  1. 설정 저장 후 JBoss 서버를 재기동(Reload)합니다.
  2. 관리 콘솔 또는 CLI에서 Test Connection을 수행하여 연결 성공 여부를 확인합니다.
  3. 연결 성공 시, 설정 파일에 비밀번호 평문이 남아있지 않은지 재확인합니다.

Next Step:
만약 비밀번호 뿐만 아니라 키스토어 패스워드 등 JBoss 설정 전반의 민감 정보를 보호해야 한다면, Vault(볼트) 구성을 추가로 검토해 보십시오.

Open Stream →
#EAP7

[JBoss EAP 7] Windows 환경 도메인 모드(Domain Mode) 구축: Master/Slave 구성 및 CLI 제어

JBoss EAP 7.2를 도메인 모드로 구성하여 중앙 집중식 관리 환경을 구축합니다. Windows Server 환경에서 마스터(Master)와 슬레이브(Slave) 호스트를 설정하고, add-user를 통해 보안 인증(Secret Value)을 처리하는 과정, 그리고 CLI를 이용한 제어 방법을 다룹니다.

0. 배경 지식 (Context)

도메인 모드는 Domain Controller(Master)가 전체 정책을 관리하고, Host Controller(Slave)들이 실제 서버 인스턴스를 구동하는 구조입니다.

  • Master: 설정 및 배포 중앙 관리 (서버 인스턴스를 직접 띄우지 않는 것을 권장)
  • Slave: 실제 애플리케이션이 구동되는 서버 그룹 관리

Test Environment

  • OS: Windows NT (10/Server)
  • Version: JBoss EAP 7.2
  • Topology: One-Box 구성 (하나의 서버에 Master/Slave 디렉토리 분리)

1. 관리자 계정 생성 및 인증 토큰 확보

도메인 컨트롤러(Master)와 호스트 컨트롤러(Slave) 간의 통신을 위해서는 보안 인증이 필요합니다. add-user.bat를 통해 계정을 생성하고 Secret Value를 확보해야 합니다.

실행 절차

F:\app\Redhat\JBoss7.2\bin> add-user.bat

# 1. 관리자 계정 선택
What type of user do you wish to add?
 a) Management User (mgmt-users.properties)
 b) Application User (application-users.properties)
(a): a

# 2. 계정 정보 입력 (Username: admin / Password 설정)
# ... (중략) ...

# 3. 프로세스 간 연결 승인 (중요!)
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master ...
yes/no? yes

# 4. 결과값 복사
To represent the user add the following to the server-identities definition
Check Point: 마지막에 출력된 <secret value="..." /> 문자열을 반드시 복사해 두십시오. Slave 설정 시 사용됩니다.

2. 설정 파일 수정 (Configuration)

Master와 Slave 각각의 host.xml 파일을 수정하여 역할을 정의합니다.

1) Master 설정 (host-master.xml)

자신이 도메인 컨트롤러임을 명시합니다.

<host xmlns="urn:jboss:domain:8.0" name="test-master">
    
    <domain-controller>
       <local/>
    </domain-controller>
    ...
</host>

2) Slave 설정 (host-slave.xml)

Master에 연결하기 위한 인증 정보와 고유한 호스트 이름을 설정합니다. 한 장비에서 띄울 경우 포트 충돌 방지를 위해 관리 포트를 변경해야 합니다.

<host xmlns="urn:jboss:domain:8.0" name="slave-node01">

    <server-identities>
        <secret value="YWRtaW4xMiMk" />
    </server-identities>

    <domain-controller>
        <remote security-realm="ManagementRealm">
            <discovery-options>
                <static-discovery name="primary" protocol="${jboss.domain.master.protocol:remote}" host="${jboss.domain.master.address}" port="${jboss.domain.master.port:9990}"/>
            </discovery-options>
        </remote>
    </domain-controller>

    <management-interfaces>
        <http-interface security-realm="ManagementRealm">
            <http-upgrade enabled="true"/>
            <socket interface="management" port="${jboss.management.http.port:19990}"/>
        </http-interface>
    </management-interfaces>
</host>

3. 도메인 기동 (Start Scripts)

디렉토리(domain/base/dir)를 분리하여 운영하는 환경을 가정한 기동 스크립트입니다.

Master 기동

F:\app\Redhat\JBoss7.2\bin\domain.bat ^
 -Djboss.domain.base.dir="F:\app\Redhat\JBoss7.2\master" ^
 -b=192.168.0.6 ^
 -bmanagement=192.168.0.6 ^
 --host-config=host-master.xml

Slave 기동 (Node 01 & 02)

Slave는 --master-address 옵션으로 Master를 바라보며, -Djboss.socket.binding.port-offset으로 서비스 포트 충돌을 방지합니다.

:: Slave Node 01 (Port Offset: 1000)
F:\app\Redhat\JBoss7.2\bin\domain.bat ^
 -Djboss.domain.base.dir="F:\app\Redhat\JBoss7.2\node01" ^
 -b=192.168.0.6 ^
 -bmanagement=192.168.0.6 ^
 --host-config=host-slave.xml ^
 --master-port=9990 ^
 --master-address=192.168.0.6 ^
 -Djboss.socket.binding.port-offset=1000

:: Slave Node 02 (Port Offset: 2000)
F:\app\Redhat\JBoss7.2\bin\domain.bat ^
 -Djboss.domain.base.dir="F:\app\Redhat\JBoss7.2\node02" ^
 -b=192.168.0.6 ^
 -bmanagement=192.168.0.6 ^
 --host-config=host-slave.xml ^
 --master-port=9990 ^
 --master-address=192.168.0.6 ^
 -Djboss.socket.binding.port-offset=2000

4. CLI를 이용한 서버 제어 (Management)

도메인 모드에서는 jboss-cli를 통해 특정 호스트의 특정 서버 인스턴스만 제어할 수 있습니다.

기본 구문

/host=[HOST_NAME]/server-config=[SERVER_NAME]:[start|stop|restart]

실행 예시

:: 접속 (Master Controller IP로 접속)
F:\app\Redhat\JBoss7.2\bin> jboss-cli.bat --connect controller=192.168.0.6:9990

:: 특정 서버(test01) 정지
[domain@192.168.0.6:9990 /] /host=slave-node01/server-config=test01:stop
{
    "outcome" => "success",
    "result" => "STOPPING"
}

:: 특정 서버(test01) 기동
[domain@192.168.0.6:9990 /] /host=slave-node01/server-config=test01:start
{
    "outcome" => "success",
    "result" => "STARTING"
}

Next Step:
구성이 완료되었다면 관리 콘솔(http://192.168.0.6:9990)에 접속하여 Runtime 탭에서 Topology가 정상적으로 인식되는지 확인하십시오.

Open Stream →