본문 바로가기

리눅스

리눅스에서 사용자 명령어(history)를 rsyslog 중앙 로그 서버로 전송하는 방법

반응형

리눅스에서 사용자 명령어(history)를 rsyslog 중앙 로그 서버로 전송하는 방법

리눅스에서 사용자의 bash 명령 이력을 실시간으로 수집하여 중앙 syslog 서버로 전송하는 방법입니다.

보안 감사(audit), 사용자 행위 추적, 운영 이력 관리에 활용할 수 있다.

전체 흐름

[클라이언트 서버]
  bash trap (DEBUG)
      ↓
  logger 명령어
      ↓
  rsyslog (local6.notice)
      ↓ TCP/UDP 514
[중앙 로그 서버]
  rsyslog (imtcp / imudp)
      ↓
  /var/log/clients/<HOSTNAME>/bash_history.log

1. Bash History → syslog 연동

trap 'function' DEBUG 를 이용하면 bash에서 명령어를 실행할 때마다 지정한 함수를 호출할 수 있다.

이 함수 안에서 logger로 syslog에 기록하는 방식이다.

 

/etc/profile.d/history.sh 작성

cat <<'EOF' > /etc/profile.d/history.sh

function history_to_syslog()
{
    # 재귀 호출 방지: 함수 진입 시 trap을 먼저 해제
    trap - DEBUG

    local cmd="${BASH_COMMAND}"

    # logger, trap 등 내부 명령어는 로깅에서 제외
    case "$cmd" in
        history_to_syslog*|\
        logger*|\
        trap*|\
        local\ cmd*|\
        who\ am\ i*|\
        tty|\
        pwd|\
        return*)
            trap 'history_to_syslog' DEBUG
            return
            ;;
    esac

    # SSH 접속 시 IP는 "(192.168.1.100)" 형태로 반환되므로 괄호 제거
    local ip
    ip=$(who am i | awk '{gsub(/[()]/,""); print $5}')
    ip=${ip:-"local"}   # 콘솔 직접 로그인 시 fallback

    logger -p local6.notice -t bash_history \
    "USER=$(whoami) \
IP=${ip} \
TTY=$(tty) \
PWD=$(pwd) \
CMD=${cmd}"

    # 함수 종료 시 trap 복원
    trap 'history_to_syslog' DEBUG
}

trap 'history_to_syslog' DEBUG

EOF

권한 설정 및 적용

chmod 644 /etc/profile.d/history.sh
source /etc/profile.d/history.sh

2. rsyslog 클라이언트 설정

TCP vs UDP 비교

항목 TCP UDP
전송 보장 O (재전송) X (유실 가능)
서버 장애 대응 queue 버퍼링 가능 불가
성능 오버헤드 상대적으로 높음 낮음
운영 환경 권장 권장 내부망 경량 수집 시

운영 환경에서는 TCP를 권장한다.

2-1. 로컬 저장 + 중앙 서버 전송

로컬 디스크에도 기록하면서 중앙 서버로도 전송하는 방식이다. 로컬 백업이 필요한 환경에 적합하다.

 

rsyslog 설정(TCP 사용 시)

sudo vim /etc/rsyslog.d/history.conf
if $programname == 'bash_history' then {
    action(type="omfile"
           file="/var/log/bash_history.log")

    action(type="omfwd"
           target="logserv.scbyun.com"
           port="514"
           protocol="tcp")
}
더보기

---

UDP 사용 시

sudo vim /etc/rsyslog.d/history.conf
if $programname == 'bash_history' then {
    action(type="omfile"
           file="/var/log/bash_history.log")

    action(type="omfwd"
           target="logserv.scbyun.com"
           port="514"
           protocol="udp")
}

---

728x90

2-2. 중앙 서버로만 전송 (로컬 저장 없음)

로컬 디스크 사용량을 줄이고 싶을 때 사용한다.

 

rsyslog 설정(TCP 사용 시)

sudo vim /etc/rsyslog.d/history.conf
if $programname == 'bash_history' then {
    action(type="omfwd"
           target="logserv.scbyun.com"
           port="514"
           protocol="tcp")
    stop
}
더보기

---

UDP 사용 시

sudo vim /etc/rsyslog.d/history.conf
if $programname == 'bash_history' then {
    action(type="omfwd"
           target="logserv.scbyun.com"
           port="514"
           protocol="udp")
    stop
}

---

stop 옵션 설정이 중요하다.
이 옵션이 있어야 /var/log/messages, /var/log/syslog 같은 로컬 로그 파일에 기록되지 않는다.

2-3. 운영 환경 권장 설정 (TCP + Disk-Assisted Queue)

linkedList(메모리 큐)는 rsyslog 재시작 시 데이터가 유실된다.

운영 환경에서는 disk-Assisted 큐를 사용하여 재시작 후에도 미전송 로그를 복구할 수 있도록 구성한다.

sudo vim /etc/rsyslog.d/history.conf
if $programname == 'bash_history' then {
    action(
        type="omfwd"
        target="logserv.scbyun.com"
        port="514"
        protocol="tcp"

        # 서버 장애 시 무한 재시도
        action.resumeRetryCount="-1"

        # 메모리+디스크 혼합 큐 (재시작 후 복구 가능)
        queue.type="disk-Assisted"
        queue.filename="bash_history_fwd"   # 스풀 파일명 (필수)
        queue.size="10000"
        queue.maxDiskSpace="100m"
    )
    stop
}

rsyslog 재시작

sudo systemctl restart rsyslog

3. 기존 rsyslog 설정과 중복 전송 방지

기존 설정에 아래와 같이 전체 전송 룰이 있다면

*.info;mail.none;authpriv.none;cron.none    @logserv.scbyun.com

local6.notice 로그도 함께 전송되어 중앙 서버에 중복으로 기록될 수 있다.

 

해결 방법: history.conf 에 stop을 추가하면 rsyslog의 rule 처리 흐름이 해당 시점에서 중단된다.

이후 *.info 룰까지 처리가 넘어가지 않으므로 중복 전송이 방지된다.

if $programname == 'bash_history' then {
    action(type="omfwd"
           target="logserv.scbyun.com"
           port="514"
           protocol="tcp")
    stop    # ← 이 줄이 있어야 이후 룰로 넘어가지 않음
}
/etc/rsyslog.d/ 디렉터리의 파일은 파일명 알파벳 순서로 로드된다.
history.conf가 기존 전송 룰보다 먼저 처리되도록 00-history.conf처럼 접두사를 붙이는 것도 좋은 방법이다.

4. 중앙 로그 서버(수신 측) 설정

중앙 서버에서 클라이언트 로그를 수신하려면 imtcp 또는 imudp 모듈을 활성화해야 한다.

sudo vim /etc/rsyslog.d/00-server.conf
# TCP 수신 활성화
module(load="imtcp")
input(type="imtcp" port="514")

# 호스트별 디렉터리로 분리 저장
if $programname == 'bash_history' then {
    action(type="omfile"
           file="/var/log/clients/%HOSTNAME%/bash_history.log"
           dirCreateMode="0750"
           fileCreateMode="0640"
           dirOwner="root"
           fileOwner="root")
    stop
}
sudo systemctl restart rsyslog
UDP를 사용할 경우 imtcp 대신 imudp를 로드하고 protocol="udp"로 맞춰준다.

5. 로그 로테이션 (logrotate)

로컬 또는 서버에 파일로 저장하는 경우 로테이션 설정이 필요하다. 미설정 시 단일 파일이 무한정 커진다.

sudo vim /etc/logrotate.d/bash_history
/var/log/bash_history.log {
    daily
    rotate 90
    compress
    missingok
    notifempty
    postrotate
        systemctl kill -s HUP rsyslog
    endscript
}

# 중앙 서버 호스트별 로그 로테이션
/var/log/clients/*/bash_history.log {
    daily
    rotate 90
    compress
    missingok
    notifempty
    sharedscripts
    postrotate
        systemctl kill -s HUP rsyslog
    endscript
}

6. 로그 확인

클라이언트 로컬

tail -f /var/log/bash_history.log

중앙 로그 서버

  • 특정 호스트 로그 확인
tail -f /var/log/clients/web01/bash_history.log
  • 전체 서버 로그에서 검색
grep bash_history /var/log/messages
May 10 10:23:45 web01 bash_history: USER=scbyun IP=192.168.1.100 TTY=/dev/pts/0 PWD=/home/scbyun CMD=ls -al
May 10 10:23:48 web01 bash_history: USER=scbyun IP=192.168.1.100 TTY=/dev/pts/0 PWD=/home/scbyun CMD=cat /etc/passwd

 

728x90
반응형