카테고리 보관물:  IT

리눅스 Shell 및 ssh 계정 잠금 설정

개요

리눅스 서버에서 SSH 로그인 실패가 반복되는 경우 해당 계정을 자동으로 잠금(lock)하도록 PAM(Pluggable Authentication Modules)을 설정할 수 있습니다. pam_tally2 또는 pam_faillock 모듈을 사용해 일정 횟수 로그인 실패 시 계정을 잠그고, 관리자가 수동으로 잠금을 해제하는 방법을 정리합니다.

  • 콘솔 및 원격 접속(ssh)시 로그인 실패시 계정 잠금 설정
  • pam_tally.so와 pam_tally2.so은 기본값 및 옵션 차이가 있음
// CentOS 5.X 버전 이하용
# /etc/pam.d/system-auth , /etc/pam.d/password-auth 에 이하 설정 추가

// 3회 입력 실패시 계정이 잠기며 잠금 초기화 간격은 2분, root 계정은 잠기지 않고 로그인이 성공하면 실패 횟수는 초기화
auth required pam_tally.so no_magic_root deny=3 unlock_time=120
account required pam_tally.so no_magic_root reset
// CentOS 6.X 버전 이상부터는 pam_tally2.so를 사용할 수 있으므로 이하 설정 권고
# /etc/pam.d/system-auth , /etc/pam.d/password-auth 에 이하 설정 추가

// 3회 입력 실패시 계정이 잠기며 잠금 초기화 간격은 2분, 기본적으로 root 계정은 잠기지 않고 성공하면 실패 횟수는 초기화됨
// even_deny_root 인수를 사용하게 되면 root 비밀번호 입력 실패시 계정이 잠길 수 있음
auth required pam_tally2.so deny=3 unlock_time=120
account required pam_tally2.so

RHEL 8 / 9에서의 pam_faillock 사용

RHEL 8 및 CentOS Stream 8 이상에서는 pam_tally2가 deprecated되고 pam_faillock으로 대체되었습니다. pam_faillock은 기존 pam_tally2와 설정 방식이 다르며, /etc/security/faillock.conf 파일을 통해 중앙에서 정책을 관리합니다. authselect 프로파일과 연동되어 PAM 설정을 일관성 있게 관리할 수 있습니다.

# /etc/security/faillock.conf 주요 설정
deny = 3              # 3회 실패 시 계정 잠금
unlock_time = 120     # 120초 후 자동 해제
even_deny_root        # root 계정도 잠금 대상 포함 (운영 환경 주의)
fail_interval = 300   # 실패 횟수 집계 기간(초)

# pam_faillock 활성화 (RHEL 8/9, authselect 사용)
# authselect select sssd with-faillock --force
# 또는 /etc/pam.d/system-auth, /etc/pam.d/password-auth에 직접 추가:
# auth required pam_faillock.so preauth silent
# auth required pam_faillock.so authfail
# account required pam_faillock.so

계정 잠금 상태 확인 및 수동 해제

계정이 잠금 상태인지 확인하고 관리자가 직접 잠금을 해제하는 방법은 pam_tally2와 pam_faillock 모두 전용 명령어를 제공합니다. 잠긴 계정을 해제하지 않으면 unlock_time이 경과해야만 자동으로 풀리므로, 업무 시간 중 긴급하게 해제해야 하는 경우 아래 명령어를 사용합니다.

# pam_tally2 (RHEL 6/7)
# 특정 계정의 실패 횟수 확인
pam_tally2 --user <admin-user>

# 잠금 해제 (실패 횟수 초기화)
pam_tally2 --user <admin-user> --reset

# pam_faillock (RHEL 8/9)
# 특정 계정의 잠금 상태 확인
faillock --user <admin-user>

# 잠금 해제
faillock --user <admin-user> --reset

PAM 잠금 정책 적용 후에는 정책이 실제로 동작하는지 테스트 계정으로 반드시 검증합니다. root 계정 잠금(even_deny_root)은 운영 서버에서는 콘솔 접근이 불가능해질 위험이 있으므로 신중히 적용해야 합니다.

SSH 접근 제어와 PAM 잠금 정책의 연계

PAM 계정 잠금 설정은 SSH 서비스의 접근 제어 설정과 함께 적용하면 더 강력한 보안을 구현할 수 있습니다. /etc/ssh/sshd_config에서 MaxAuthTries를 낮게 설정하면 SSH 레이어에서 먼저 접속을 끊고, PAM 레이어에서 누적 실패 횟수를 집계하여 계정을 잠급니다. 두 설정은 독립적으로 동작하므로 함께 적용해야 시너지를 발휘합니다.

운영 서버에 권장되는 SSH 보안 강화 항목은 다음과 같습니다. PermitRootLogin no로 root SSH 직접 로그인을 차단하고, PasswordAuthentication no로 공개키 인증만 허용하면 brute force 공격 시도 자체를 원천 차단할 수 있습니다. 공개키 인증만 허용하는 환경에서는 PAM 비밀번호 잠금의 실질적 의미가 줄어들지만, su/sudo 등 로컬 인증 경로를 통한 무차별 대입 공격 방지를 위해 PAM 잠금 정책은 여전히 유효합니다.

PAM 설정 변경 후에는 반드시 별도의 세션(SSH 창)을 열어둔 상태에서 변경 사항을 적용해야 합니다. 잘못된 설정으로 모든 인증이 차단될 경우 콘솔 접근이나 다른 열린 세션을 통해 복구할 수 있습니다.

참고

참고 문서: pam_tally2 매뉴얼 페이지 · RHEL PAM 보안 강화 가이드

WordPress 설치(Apache base)

개요

CentOS 7 환경에서 Apache(httpd) 기반으로 WordPress 설치를 진행하는 전체 절차입니다. Apache → PHP → MariaDB 순서로 설치하고 WordPress 패키지를 DocumentRoot에 배포한 후, wp-config.php에 DB 연결 정보와 Salt 값을 설정하면 브라우저에서 WordPress 설치 마법사 화면에 접근할 수 있습니다.

구성 개요

Apache, PHP, MariaDB 세 컴포넌트를 같은 서버에 설치하는 방식을 LAMP 스택(Linux + Apache + MySQL/MariaDB + PHP)이라 합니다. LAMP 스택은 WordPress의 가장 전통적인 배포 방식으로, 소규모 서비스나 내부 서버에서 간단하게 구성할 수 있습니다. Apache는 PHP 요청을 mod_php로 처리하고, MariaDB는 WordPress의 게시글, 사용자, 설정 데이터를 저장합니다. 이 가이드는 CentOS 7 기준으로 작성되었으나 Rocky Linux 8/9에서도 DNF 명령과 패키지 이름만 일부 변경하면 동일하게 적용할 수 있습니다.

설치 환경

  • OS: CentOS 7 64bit
  • Web Server: Apache 2.4 + mod_ssl
  • Language: PHP 7.2
  • Database: MariaDB 10.3

Apache 설치

mod_ssl 모듈을 포함하여 Apache를 설치합니다. HTTPS를 사용하려면 mod_ssl이 반드시 필요합니다.

# yum install httpd httpd-devel mod_ssl -y

httpd.conf에 VirtualHost 설정을 추가합니다. HTTP 요청은 HTTPS로 리다이렉트하고, SSL VirtualHost에 인증서 경로를 지정합니다. Self-signed 인증서 생성 방법은 Apache HTTPS 구성 — mod_ssl 설치 및 self-signed 인증서 생성을 참고하세요.

<VirtualHost *:80>
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
  DocumentRoot /app/doc/wordpress
  ServerName www.<domain>
  ServerAlias www.<domain>
</VirtualHost>

<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile /etc/pki/tls/certs/ca.crt
  SSLCertificateKeyFile /etc/pki/tls/private/ca.key
  DocumentRoot /app/doc/wordpress
  ServerName www.<domain>
  ServerAlias www.<domain>
</VirtualHost>

ssl.conf에서 인증서 파일 경로를 지정합니다.

SSLCertificateFile /etc/pki/tls/certs/ca.crt
SSLCertificateKeyFile /etc/pki/tls/private/ca.key

PHP 설치

WordPress 운영에 필요한 PHP 7.2와 관련 확장 모듈을 webtatic 저장소를 통해 설치합니다.

# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
# yum install mod_php72w php72w-cli -y
# yum install php72w-bcmath php72w-gd php72w-mbstring php72w-mysqlnd php72w-pear php72w-xml php72w-xmlrpc php72w-process -y

# 설치 버전 확인
# php -v

MariaDB 설치 및 WordPress DB 생성

MariaDB 설치 방법은 MariaDB 10.3 설치를 참고하세요. MariaDB 설치 완료 후 WordPress 전용 데이터베이스와 계정을 생성합니다.

# mysql -u root -p

> CREATE DATABASE wordpress CHARACTER SET utf8 COLLATE utf8_bin;
> GRANT ALL PRIVILEGES ON wordpress.* TO wordpress@'localhost' IDENTIFIED BY 'password';
> FLUSH PRIVILEGES;

WordPress 설치 및 설정

WordPress 최신 패키지를 다운로드하고 DocumentRoot 경로에 배포한 후 권한을 설정합니다.

# wget https://wordpress.org/latest.tar.gz
# tar zxvf latest.tar.gz

# mv wordpress /app/doc/
# mkdir /app/doc/wordpress/wp-content/uploads
# chown -R apache:apache /app/doc/wordpress
# chmod -R 755 /app/doc/wordpress

# cd /app/doc/wordpress
# mv wp-config-sample.php wp-config.php

wp-config.php에 DB 연결 정보를 입력합니다.

# vi wp-config.php

define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'wordpress');
/** MySQL database password */
define('DB_PASSWORD', 'password');   // 실제 비밀번호로 변경
/** MySQL hostname */
define('DB_HOST', 'localhost');

Salt 값 설정: WordPress Salt Generator에 접속하여 출력된 텍스트를 복사한 후 wp-config.php의 'put your unique phrase here' 항목 전체를 교체합니다.

설치 완료 후 보안 강화

WordPress 설치 마법사를 완료한 후 다음 보안 설정을 추가로 진행합니다. WordPress의 xmlrpc.php는 외부 원격 게시 기능을 제공하지만, 무차별 대입 공격(brute-force)에 자주 악용됩니다. 사용하지 않는다면 Apache에서 접근을 차단합니다. 또한 WordPress 관리자 계정 이름을 admin으로 그대로 사용하면 공격 대상이 되므로, 첫 설치 시 다른 이름으로 설정하거나 설치 후 변경합니다.

# httpd.conf 또는 .htaccess에서 xmlrpc.php 접근 차단
<Files xmlrpc.php>
  Order Deny,Allow
  Deny from all
</Files>

WordPress 파일과 디렉토리 권한은 보안과 기능성의 균형이 중요합니다. PHP가 파일 업로드 및 플러그인 설치를 처리하려면 wp-content/uploadswp-content/plugins에 Apache 프로세스 계정(apache 또는 www-data)의 쓰기 권한이 필요합니다. 그러나 웹 디렉토리 전체를 777로 설정하는 것은 보안 위험이 있으므로, 755(디렉토리)와 644(파일) 조합을 기본으로 하고 uploads 디렉토리만 쓰기 권한을 부여합니다.

서비스 시작 및 접속 확인

Apache 서비스를 시작하고 브라우저에서 서버 IP 또는 도메인 주소로 접속하면 WordPress 설치 마법사 화면이 표시됩니다.

# systemctl enable httpd
# systemctl start httpd

브라우저에서 https://<서버IP>에 접속하면 WordPress 언어 선택 화면이 표시됩니다.

참고

참고 문서: WordPress 공식 설치 가이드 · Apache HTTP Server 2.4 공식 문서

MariaDB 10.3 설치

개요

MariaDB는 MySQL의 오픈소스 포크로, MySQL과 거의 동일한 SQL 문법과 드라이버를 지원하면서 성능 개선과 추가 기능을 제공합니다. CentOS 7 기본 yum 저장소에는 MariaDB 5.5가 포함되어 있어, 10.3 이상의 버전을 설치하려면 공식 MariaDB 저장소를 추가해야 합니다. MariaDB 10.3은 장기 지원(LTS) 버전으로 안정성이 검증되어 있으며 WordPress, Zabbix, rsyslog 등 다양한 애플리케이션과 호환됩니다.

이 글에서는 CentOS 7 환경에 MariaDB 10.3을 설치하는 방법을 정리합니다. MariaDB 공식 yum 리포지토리를 등록한 후 패키지를 설치하고, 초기 보안 설정(mysql_secure_installation)을 진행하여 운영 환경에서 사용할 수 있는 상태로 구성하는 절차를 다룹니다.

1. yum repository 경로 설정

# vi /etc/yum.repos.d/MariaDB.repo

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

2. 패키지 설치 및 서비스 실행

# yum install MariaDB-client MariaDB-server -y

# systemctl enable mariadb
# systemctl start mariadb

3. mariadb 접속 확인 및 비밀번호 설정

# mysql -u root

> use mysql;

> update user set password = password('새비밀번호') where user='root';
// 비밀번호 설정('') 넣어야 됨
> flush privileges;

mysql_secure_installation 보안 설정

MariaDB 설치 후 초기 상태에서는 root 계정에 비밀번호가 없고 익명 사용자 계정이 존재하는 등 보안이 취약합니다. mysql_secure_installation을 실행하면 대화형으로 보안 강화 설정을 진행할 수 있습니다.

# mysql_secure_installation

# 주요 질문과 권장 답변:
# Set root password? → Y, 강력한 비밀번호 입력
# Remove anonymous users? → Y (익명 사용자 제거)
# Disallow root login remotely? → Y (root 원격 접속 차단)
# Remove test database? → Y (테스트 DB 제거)
# Reload privilege tables? → Y (권한 테이블 즉시 반영)

보안 설정 완료 후 root 비밀번호로 로그인되는지 확인합니다. 애플리케이션 전용 계정은 root 대신 별도 계정을 생성하고 필요한 DB에만 권한을 부여하는 최소 권한 원칙을 따르는 것이 권장됩니다.

캐릭터셋 및 시간대 설정

한국어 데이터와 이모지를 올바르게 저장하려면 캐릭터셋을 utf8mb4로 설정합니다. /etc/my.cnf.d/mariadb-server.cnf(또는 /etc/my.cnf)에 아래 설정을 추가합니다.

[mysqld]
character-set-server = utf8mb4
collation-server     = utf8mb4_unicode_ci
default-time-zone    = '+09:00'

[client]
default-character-set = utf8mb4

설정 변경 후 systemctl restart mariadb로 서비스를 재시작하고, SHOW VARIABLES LIKE 'character%'로 적용 여부를 확인합니다.

초기 데이터베이스 및 계정 생성

MariaDB 설치 후 애플리케이션 전용 데이터베이스와 계정을 생성하는 것이 기본 설정 마무리 단계입니다. root 계정을 직접 사용하는 것보다 애플리케이션별 전용 계정을 만들고 필요한 데이터베이스에만 권한을 부여하는 최소 권한 원칙을 따릅니다. 아래는 WordPress용 DB와 계정 생성 예시입니다.

-- MariaDB root로 접속
$ mysql -u root -p

-- 데이터베이스 생성 (utf8mb4 charset 지정)
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 전용 계정 생성 및 권한 부여
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY '<REDACTED>';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;

-- 계정 및 권한 확인
SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'wp_user'@'localhost';

원격 접속이 필요한 경우 'wp_user'@'%'로 생성하되, 방화벽에서 3306 포트를 신뢰하는 IP 대역으로만 제한하는 것이 권장됩니다. MariaDB의 bind-address 설정을 통해 특정 인터페이스에서만 리스닝하도록 제한하면 추가적인 보안 레이어를 확보할 수 있습니다. 계정 생성 후 mysql -u wp_user -p wordpress로 접속이 정상적으로 되는지 반드시 검증합니다.

참고

참고 문서: MariaDB yum 리포지토리 설정 공식 문서 · mysql_secure_installation 가이드