개발

SFTP 접근 기록 남기는 방법 (Auditd)

by 에루샤
우리 회사,
그러니까 기존 레거시 코드로 운영하는 환경에서는 '형상관리'는 좀 꿈과 같다.


1. 현실적인 제한

아예 적용불가능 수준을 거론하는게 아니라, 현실적인 문제에 봉착하는 느낌이라 볼 수 있다.
몇가지 문제를 이야기해볼 수 있는데,

1) 이미 레거시 코드와 라이브 패키지 서비스로 구현

프로젝트를 시작하는 곳이 아니라면 공통적으로 가지고 있는 문제점이다.

이미 기존 프로젝트가 라이브 서버에서 코드를 조율하면서 만들어져있다는 것이다.

뭔가 나아지기위해서 변화는 필요하다만, 이미 "잘 돌아가는 시스템" 이 있다면, 기업 입장에선 리스크를 질 필요가 전혀 없다는 것이다.

특히나 그런 시스템이 다른 부서의 뭔가랑 연동이 되어있다면 이건 참 손대기도 힘든 수준이다.


2) 작업자의 교육 한계

1번의 예와 비슷하지만 이미 기존 방식으로 작업을 했던 사람들의 무수한 반대다.

이미 검증된 방법으로 몇년동안 운영해왔고, 그 방식으로 문제없이 돌아갔는데 왜 굳이 긁어 부스럼을 만드느냐라는 관점은 정말 무시하기 힘든 부분이긴하다.
차라리 문제점이 보고되면 그걸 기준으로 말을 꺼내는 경우가 있겠지만 말이다.

더불어 새로운 것을 공부하고 본업에 적용하는걸 극도로 싫어하는 직원들과 함께 협업하는 코드라면...
말을 말자...


3) 웹사이트 서비스에서의 형상관리라면

우리는 인터프리터, PHP 방식의 웹 서버를 운용중이다.
인터프리터 언어는 수정사항이 바로 반영될 정도로 즉각적인 서비스를 할 수 있지만, 이 때문에 형상관리를 적용하는데 "굳이?"라는 질의를 정말 많이 받는 언어이기도 하다.

도중 프로젝트에 형상관리를 넣든, 새로 시작하든, 굳이 코드 저장소와 커밋, 푸시 과정을 '불필요'하게 느껴질 정도의 생산 효율성이 PHP에 있다보니까, 그런게 왜 필요하냐는 반문이다.



물론 이렇게 언급한 세가지 이유가 일종의 핑계일수도 있을 것이다.
형상관리를 하지 않았을 때 생기는 문제는 다들 알고있고 그 상황에서 시선을 돌리는 것일 뿐.



2. 보완 방법

자, 그럼 이렇게 비협조적인 상황에서 만약에 공용코드가 '어떤 사건'에 의해 침해되었다면 서버 관리자는 뭘 어떻게 할 수 있을까?

제일 쉽게 생각할 수 있는게 백업 시스템이다.
주기적으로 라이브 서버를 백업해두고 문제가 발생하면 롤백하는 구조다.

하지만 이런 백업도 마지막 백업이후의 데이터는 증발하긴 마찬가지고, 제일 좋은건 그런 사건이 발생하지 않는것이다.
그걸 위한 형상관리지만, 안되는걸 어떻해?


그럼 '추궁'이라도 해야하지 않겠는가?
한편으로는 보안적 관점에서 FTP로 접속해 파일을 수정하는 작업자들을 모두 감시하는거지만, 만약 모종의 사건이 일어난다면 누가 잘못했는지 파악해야 그사람을 교육하든, 제재를 하든 할 것이다.

왜냐고?
최근에 비슷한 일이 일어났는데, 끝가지 발뺌하더라


어찌됐든 우분투 환경에서 이런 FTP 작업을 감사할 수 있는 기능이 있냐 하면 기본적으론 없다.
계정의 로그인정도를 남기는 auth.log 정돈 있지만, 파일 감시까진 기본적으로 깔려있지 않다.

필요하면 찾아서 설치해라, 그게 우분투, 리눅스 작업이지 않겠는가?


3. auditd

설치와 세팅을 해보자

3-1. 패키지 설치

sudo apt install auditd
Copy

먼저 해당 패키지를 설치해주자.
제대로 설치되었는지 확인하려면 아래 명령어를 쳤을때 뭐가 나오면 설치가 잘된 것

dpkg -l | grep -E '^ii\s+auditd\b'
apt-cache policy auditdCopy


3-2. 룰 생성

어느 폴더를 감시할지 룰을 만들어주자.

sudo tee /etc/audit/rules.d/www_8100_source.rules >/dev/null <<'EOF'
-w /home/ubuntu/www/8100/app -p wa -k src_8100
-w /home/ubuntu/www/8100/config -p wa -k src_8100
-w /home/ubuntu/www/8100/database -p wa -k src_8100
-w /home/ubuntu/www/8100/public -p wa -k src_8100
-w /home/ubuntu/www/8100/resources -p wa -k src_8100
-w /home/ubuntu/www/8100/routes -p wa -k src_8100
EOFCopy

뭐 좀 복잡하지면 결국 그거다.

룰 폴더 rules.d 를 만들고 그안에 룰파일 www_8100_source.rules 을 만들어 감시할 폴더를 적어주면된다.
위 명령어는 w(읽기)와 a(권한변경)에 대해 감시를 걸으며, 해당 감시기록에 src_8100이라는 태그를 남기는 옵션이라 볼 수 있다.

난 라라벨 프로젝트도 보니까 실제 작업자들이 건드리는 폴더만 감시를 걸어두었다.
node_modules이나 storage, vendeor등을 감시를 걸면 쓸데없는 로그가 너무많이 쌓이니 선택적으로 감시를 걸어두는게 필요하다.


3-3. 자동 룰 생성

단일 프로젝트라면 위에처럼 하면 끝이지만 다중 프로젝트라면 위의 룰를 몇십, 몇백줄을 적어줘야한다.

당연히 정상적인 작업은 아니므로, 이를 자동화 할 수있는 쉘 스크립트를 만들어보자.

sudo nano /usr/local/sbin/audit-refresh-www-rules.shCopy

먼저 이렇게 스크립트를 만들어주고, 파일 편집창에서 아래 스크립트를 넣어준다.

#!/usr/bin/env bash
set -euo pipefail

BASE="/var/www"
OUT="/etc/audit/rules.d/www_sources.rules"
DIRS=(app config database public resources routes)

echo "# auto-generated $(date -Is)" > /tmp/www_sources.rules

for p in "$BASE"/*; do
  [ -d "$p" ] || continue
  name="$(basename "$p")"
  key="builder_${name}"
  for d in "${DIRS[@]}"; do
    if [ -d "$p/$d" ]; then
      echo "-w $p/$d -p wa -k $key" >> /tmp/www_sources.rules
    fi
  done
done

sudo mv /tmp/www_sources.rules "$OUT"
sudo augenrules --load
sudo systemctl restart auditd
echo "OK: refreshed audit rules in $OUT"Copy

순차적으로 보자면 배쉬런을 통해서 /var/www 하위에 있는 프로젝트 폴더를 전부 순회하면서 지정한 서브 폴더명이 있으면 해당 감시 룰을 만드는 스크립트다.
이 스크립트는 /tmp/www_sources.rules 위치에 임시로 저장하고 있다가 모든 작업이 완료되고나면 기존 룰파일과 교체한다.

이렇게 만든 파일을 아래 명령어로 실행시켜주면 한방에 모든 프로젝트 폴더에 대해서 자동감시룰이 작성된다.

/usr/local/sbin/audit-refresh-www-rules.shCopy


3-4. 로그레이트 설정

작업이 빈번하게 이루어지는 서버라면 이런 감사기록도 미친듯이 불어나기 시작한다.
그래서 기본적으로 로그레이트가 적용되어있는데, 기존 수치가 엄청 낮게 설정되어있다.

이를 현실적인 사이즈로 바꾸는 방법을 알아보자.

sudo nano /etc/audit/auditd.confCopy

이 파일을 열면 auditd의 설정값을 볼 수 있는데,

local_events = yes
write_logs = yes
log_file = /var/log/audit/audit.log
log_group = adm
log_format = RAW
flush = INCREMENTAL_ASYNC
freq = 50
max_log_file = 8
num_logs = 5
priority_boost = 4
disp_qos = lossy
dispatcher = /sbin/audispd
name_format = NONE
##name = mydomain
max_log_file_action = ROTATE
space_left = 75
space_left_action = SYSLOG
verify_email = yes
action_mail_acct = root
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
use_libwrap = yes
##tcp_listen_port = 60
tcp_listen_queue = 5
tcp_max_per_addr = 1
##tcp_client_ports = 1024-65535
tcp_client_max_idle = 0
enable_krb5 = no
krb5_principal = auditd
##krb5_key_file = /etc/audit/audit.key
distribute_network = noCopy

기본값은 위와 같다.
여기서 로그파일의 크기와 최대 몇개까지 저장할지 바꿔주면된다.

max_log_file = 50
num_logs = 20Copy

로그파일의 크기는 개당 50MB로, 최대 20개가 쌓이게 해서 1기가정도의 용량을 점유하게 구성한다.

그리고 시스템의 디스크 공간이 줄어들 경우에는 로그레이트 경고를 주기위해 디스크 여유한도를 아래와 같이 설정한다.

space_left = 8192
space_left_action = SYSLOG
admin_space_left = 4096
admin_space_left_action = SYSLOGCopy

이렇게 설정해두면 디스크공간이 8GB 남았을때 경고가 한번, 4GB가 남았을 때 더 강한 경고를 보내줄 수 있다.


3-5. 로그 기록 조회

이렇게 쌓인 로그기록은 아래 명령어로 실시간으로 볼 수 있다.

sudo tail -f /var/log/audit/audit.logCopy

또는 위에서 태그로 단 키워드를 통해 아래와 같이 특정 프로젝트 로그만 걸러서 볼 수도 있다.

sudo ausearch -k builder_8100 --start todayCopy


실제 로그는 아래와 같다.

----
type=PROCTITLE msg=audit(02/24/26 15:02:01.269:5644) : proctitle=/usr/lib/openssh/sftp-server 
type=PATH msg=audit(02/24/26 15:02:01.269:5644) : item=1 name=/var/www/demo/app/Http/Controllers/Admin/FeeController.php inode=3197781 dev=103:01 mode=file,644 ouid=kiweb ogid=www-data rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
type=PATH msg=audit(02/24/26 15:02:01.269:5644) : item=0 name=/var/www/demo/app/Http/Controllers/Admin/ inode=3197775 dev=103:01 mode=dir,sgid,775 ouid=kiweb ogid=www-data rdev=00:00 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
type=CWD msg=audit(02/24/26 15:02:01.269:5644) : cwd=/home/kiweb 
type=SYSCALL msg=audit(02/24/26 15:02:01.269:5644) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffff9c a1=0x563f96ccd390 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=28422 pid=5340 auid=kiweb uid=kiweb gid=www-data euid=kiweb suid=kiweb fsuid=kiweb egid=www-data sgid=www-data fsgid=www-data tty=(none) ses=46453 comm=sftp-server exe=/usr/lib/openssh/sftp-server key=builder_demo 
----
type=PROCTITLE msg=audit(02/24/26 15:58:26.128:5892) : proctitle=/usr/lib/openssh/sftp-server 
type=PATH msg=audit(02/24/26 15:58:26.128:5892) : item=1 name=/var/www/demo/resources/views/app/home.blade.php inode=3197908 dev=103:01 mode=file,644 ouid=kiweb ogid=www-data rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
type=PATH msg=audit(02/24/26 15:58:26.128:5892) : item=0 name=/var/www/demo/resources/views/app/ inode=3197847 dev=103:01 mode=dir,sgid,775 ouid=kiweb ogid=www-data rdev=00:00 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 
type=CWD msg=audit(02/24/26 15:58:26.128:5892) : cwd=/home/kiweb 
type=SYSCALL msg=audit(02/24/26 15:58:26.128:5892) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffff9c a1=0x55f855949f40 a2=O_WRONLY|O_CREAT|O_TRUNC a3=0x1b6 items=2 ppid=19146 pid=19147 auid=kiweb uid=kiweb gid=www-data euid=kiweb suid=kiweb fsuid=kiweb egid=www-data sgid=www-data fsgid=www-data tty=(none) ses=46429 comm=sftp-server exe=/usr/lib/openssh/sftp-server key=builder_demo Copy

좀 복잡한데, 이 로그에는 ftp나 기타 프로세스 액션을 통해 감시를 걸어둔 폴더의 파일 중 쓰기나 권한수정이 발생한 기록을 볼 수 있다.

이렇게 ftp를 통해 작업을 하는 환경에서도 형상관리까진 아니어도 충분한 접근기록을 남기는 것이 가능했다.



4. 마무리

결국은 이 모든게 형상관리를 못하다보니 돌고 돌아 기록이라도 남기자는 생각으로 시작하게된 작업이다.

보안적 입장에서도 비인가 접속을 조회할 수도 있고 나름 나쁘지 않은 도달점이긴하나, 근본적인 소스코드의 안정성을 보완해주지는 않기때문에...

한계는 있다고 생각한다.


원래는 사용자별로 계정을 전부 따로 만들고 작업그룹만 통일해서 좀 더 빡빡한 접근로그를 남기고싶었는데, 그렇게하니 파일의 기본 권한문제 때문에 만져야하는 파트가 하나둘이 아니라...

이정도로 만족하기로했다.


이렇게라도 정리하지않으면 나중에 도대체 뭔 고민으로 이 작업을 했는지도 모를거 같으므로...
이렇게 작업기록을 개발글로 남겨보고자 한다.

#Ubuntu #SSH
0 개의 댓글
×