단계별 가이드: Linux 서버 보안 강화 - SSH 보안, 방화벽, 침입 탐지, 감사, 시스템 구성을 다루며 공격 표면을 줄이고 방어력을 향상시킵니다.
리눅스 서버를 보안하는 방법에 대한 진화하는 가이드입니다. 보안의 중요성과 그 이유를 조금이나마 배울 수 있기를 바랍니다.
(목차는 nGitHubTOC로 생성됨)
이 가이드의 목적은 리눅스 서버를 보안하는 방법을 가르치는 것입니다.
리눅스 서버를 보안하기 위해 할 수 있는 많은 일들이 있으며, 이 가이드는 가능한 한 많은 것들을 다루려고 합니다. 제가 배우거나 사람들이 기여함에 따라 더 많은 주제/자료가 추가될 예정입니다.
이 가이드의 Ansible 플레이북은 How To Secure A Linux Server With Ansible (by moltenbit)에서 확인할 수 있습니다.
(목차로)
여러분이 이 가이드를 사용하는 이유는 이미 좋은 보안이 왜 중요한지 이해하고 있기 때문이라고 가정합니다. 그것은 그 자체로 무거운 주제이며, 이를 분석하는 것은 이 가이드의 범위를 벗어납니다. 만약 그 질문에 대한 답을 모르신다면, 먼저 연구해 보시기를 권합니다.
높은 수준에서, 서버와 같은 장치가 공개 도메인(즉, 외부 세계에 보이는 상태)에 놓이는 순간, 악의적인 행위자의 표적이 됩니다. 보안되지 않은 장치는 여러분의 데이터에 접근하거나 여러분의 서버를 대규모 DDOS 공격의 또 다른 노드로 사용하려는 악의적인 행위자에게 놀이터가 됩니다.
더 나쁜 것은, 좋은 보안이 없다면 서버가 손상되었는지 절대 알지 못할 수도 있다는 것입니다. 악의적인 행위자가 여러분의 서버에 무단 접근하여 데이터를 복사했지만 아무것도 변경하지 않았다면, 여러분은 절대 알 수 없습니다. 또는 서버가 DDOS 공격의 일부였을 수도 있지만, 여러분은 알지 못할 것입니다. 뉴스에서 보도되는 많은 대규모 데이터 유출 사고를 보면, 기업들은 종종 악의적인 행위자가 떠난 후 한참이 지나서야 데이터 유출이나 침입을 발견했습니다.
대중적인 믿음과 달리, 악의적인 행위자가 항상 무언가를 변경하거나 돈을 받고 데이터에서 잠그려고 하는 것은 아닙니다. 때로는 데이터 웨어하우스를 위해 서버의 데이터만 원하거나(빅데이터에는 큰 돈이 있습니다), 은밀하게 서버를 자신들의 사악한 목적에 사용하려는 경우도 있습니다.
(목차로)
이 가이드는 중복/불필요해 보일 수 있습니다. 왜냐하면 리눅스를 보안하는 방법을 알려주는 수많은 온라인 글이 있지만, 그 정보는 서로 다른 주제를 다루고, 서로 다른 방식으로 작성된 여러 글에 흩어져 있기 때문입니다. 누가 수백 개의 글을 샅샅이 뒤질 시간이 있을까요?
데비안 빌드를 연구하면서 메모를 남겼습니다. 마지막에 저는 이미 알고 있던 것과 배우고 있던 것을 바탕으로 어떻게 하면 되는지에 대한 가이드의 재료가 갖춰졌음을 깨달았습니다. 다른 사람들이 배우고 시간을 절약하는 데 도움이 되도록 온라인에 올리기로 했습니다.
모든 것을 다루는 가이드는 한 번도 본 적이 없습니다. 이 가이드는 그 시도입니다.
이 가이드에서 다루는 많은 내용은 다소 기본적이거나 사소할 수 있지만, 대부분의 사람들은 매일 리눅스를 설치하지 않으며, 그런 기본적인 것들을 잊기 쉽습니다.
(목차로)
전문가, 업계 리더, 배포판 자체에서 제공하는 많은 가이드가 있습니다. 해당 가이드의 모든 내용을 포함하는 것은 실용적이지 않으며 때로는 저작권에 위배됩니다. 이 가이드를 시작하기 전에 그 가이드들을 확인해 보시기를 권장합니다.
(목차로)
(목차로)
이 가이드는...
(목차로)
서버에는 다양한 유형과 다양한 사용 사례가 있습니다. 저는 이 가이드를 가능한 한 일반적으로 만들고 싶지만, 모든 사용 사례에 적용되지 않을 수 있는 사항이 있을 것입니다. 이 가이드를 진행할 때 최선의 판단을 사용하십시오.
이 가이드에서 다루는 많은 주제에 맥락을 제공하기 위해, 제 사용 사례/구성은 다음과 같습니다:
(목차로)
저는 매우 게을러서 필요하지 않으면 파일을 직접 편집하는 것을 좋아하지 않습니다. 또한 다른 모든 사람들도 저와 같을 것이라고 가정합니다. :)
따라서 가능한 경우, 설정 파일에 줄을 추가하거나 변경하는 등 필요한 작업을 빠르게 수행할 수 있는 코드 스니펫을 제공했습니다.
코드 스니펫은 echo, cat, sed, awk, grep과 같은 기본 명령어를 사용합니다. 각 명령어/부분이 어떻게 작동하는지 등 코드 스니펫의 작동 방식은 이 가이드의 범위를 벗어납니다. man 페이지가 여러분의 친구입니다.
참고: 코드 스니펫은 변경 사항이 실제로 적용되었는지(예: 줄이 실제로 추가되거나 변경되었는지) 확인/검증하지 않습니다. 확인 부분은 여러분의 능력에 맡기겠습니다. 이 가이드의 단계에는 변경될 모든 파일의 백업을 포함하고 있습니다.
모든 변경 사항을 코드 스니펫으로 자동화할 수 있는 것은 아닙니다. 그러한 변경 사항은 구식의 수동 편집이 필요합니다. 예를 들어, INI 유형 파일에 단순히 줄을 추가할 수는 없습니다. 여러분이 좋아하는 리눅스 텍스트 편집기를 사용하십시오.
(목차로)
이 가이드를 GitHub에 올려 협업을 쉽게 하고 싶었습니다. 더 많은 사람들이 기여할수록 이 가이드는 더 좋아지고 완성도가 높아질 것입니다.
기여하려면 포크하여 풀 리퀘스트를 제출하거나 새 이슈를 제출할 수 있습니다.
(목차로)
시작하기 전에 여러분의 원칙이 무엇인지 파악해야 합니다. 위협 모델은 무엇입니까? 생각해 볼 몇 가지 사항:
이는 생각해 볼 몇 가지 사항에 불과합니다. 서버 보안을 시작하기 전에 무엇을, 왜 보호하려는지 이해하여 무엇을 해야 하는지 알아야 합니다.
(목차로)
이 가이드는 배포판에 중립적이도록 의도되어 사용자가 원하는 모든 배포판을 사용할 수 있습니다. 하지만 몇 가지 염두에 두어야 할 사항이 있습니다.
다음과 같은 배포판을 원합니다...
(목차로)
리눅스 설치는 이 가이드의 범위를 벗어납니다. 각 배포판마다 설치 방법이 다르고 설치 지침은 일반적으로 잘 문서화되어 있기 때문입니다. 도움이 필요하면 해당 배포판의 문서를 먼저 확인하십시오. 배포판에 관계없이 높은 수준의 프로세스는 일반적으로 다음과 같습니다:
가능한 경우 전문가 설치 옵션을 사용하여 서버에서 실행되는 항목을 더 세밀하게 제어하십시오. 절대적으로 필요한 것만 설치하십시오. 개인적으로 저는 SSH 외에는 아무것도 설치하지 않습니다. 또한 디스크 암호화 옵션을 선택하십시오.
(목차로)
sudo apt update && sudo apt upgrade)./etc/fstab에서 마운트 지점 구성man과 같은 원하는 핵심 소프트웨어 설치(목차로)
apt 명령어를 제공할 것입니다. 다른 배포판에 대한 해당 명령어를 제공하려는 분이 계시면 추가하겠습니다.(목차로)
이 가이드의 Ansible 플레이북은 How To Secure A Linux Server With Ansible에서 확인할 수 있습니다.변수를 필요에 맞게 편집하고 모든 작업을 미리 읽어 시스템이 손상되지 않는지 확인하세요. 플레이북을 실행한 후 모든 설정이 요구 사항에 맞게 구성되었는지 확인하십시오!
5. 필요에 따라 *group_vars/variables.yml*의 모든 변수를 변경하십시오.
6. 플레이북을 실행하기 전에 SSH 루트 액세스를 활성화하십시오: ```
nano /etc/ssh/sshd_config
[...]
PermitRootLogin yes
[...]
서버를 설치할 때 지정한 루트 비밀번호를 사용하여 요구 사항 플레이북을 실행하세요:
ansible-playbook --inventory hosts.yml --ask-pass requirements-playbook.yml
variables.yml 파일에서 지정한 새 사용자 비밀번호를 사용하여 메인 플레이북을 실행하세요:
ansible-playbook --inventory hosts.yml --ask-pass main-playbook.yml
플레이북을 여러 번 실행해야 하는 경우 SSH 키와 새 SSH 포트를 사용하는 것을 잊지 마세요:
ansible-playbook --inventory hosts.yml -e ansible_ssh_port=SSH_PORT --key-file /PATH/TO/SSH/KEY main-playbook.yml
(목차)
SSH 구성 변경 사항을 적용하고 적용하기 전에 서버에 두 번째 터미널을 열어 두는 것이 좋습니다. 이렇게 하면 첫 번째 터미널 세션에서 잠겨 나와도 연결된 세션이 하나 더 있어 문제를 해결할 수 있습니다.
이 아이디어를 제공한 Sonnenbrand에게 감사드립니다.
SSH 공개/개인 키를 사용하는 것은 비밀번호를 사용하는 것보다 더 안전합니다. 또한 서버에 연결할 때 비밀번호를 입력할 필요가 없어 더 쉽고 빠릅니다.
자세한 내용은 아래 참조를 확인하세요. 높은 수준에서 공개/개인 키는 키 쌍을 사용하여 신원을 확인하는 방식으로 작동합니다.
SSH의 경우 클라이언트에서 공개 키와 개인 키가 생성됩니다. 두 키 모두 안전하게 보관해야 하며, 특히 개인 키는 더욱 그렇습니다. 공개 키는 공개용이지만, 두 키 모두 잘못된 사람의 손에 들어가지 않도록 주의하는 것이 현명합니다.
SSH 서버에 연결할 때 SSH는 연결하려는 서버의 ~/.ssh/authorized_keys 파일에서 연결하는 클라이언트와 일치하는 공개 키를 찾습니다. 이 파일은 연결하려는 사용자 ID의 홈 폴더에 있습니다. 따라서 공개 키를 만든 후에는 ~/.ssh/authorized_keys에 추가해야 합니다. 한 가지 방법은 USB 스틱에 복사하여 물리적으로 서버로 전송하는 것입니다. 다른 방법은 ssh-copy-id를 사용하여 공개 키를 전송하고 추가하는 것입니다.
키가 생성되고 공개 키가 호스트의 ~/.ssh/authorized_keys에 추가된 후, SSH는 공개 키와 개인 키를 사용하여 신원을 확인한 다음 보안 연결을 설정합니다. 신원 확인 방법은 복잡하지만 Digital Ocean에 잘 설명되어 있습니다. 높은 수준에서 서버는 공개 키로 챌린지 메시지를 암호화한 후 클라이언트에 보내어 신원을 확인합니다. 클라이언트가 개인 키로 챌린지 메시지를 복호화할 수 없으면 신원이 확인되지 않아 연결이 설정되지 않습니다.
더 안전한 것으로 간주되는 이유는 SSH 연결을 설정하려면 개인 키가 필요하기 때문입니다. /etc/ssh/sshd_config에서 PasswordAuthentication no를 설정하면 SSH는 개인 키 없이는 연결을 허용하지 않습니다.
키에 암호를 설정할 수도 있습니다. 이 경우 공개/개인 키를 사용하여 연결할 때 키 암호를 입력해야 합니다. 이렇게 하면 스크립트에서 암호를 보낼 방법이 없기 때문에 자동화에 키를 사용할 수 없습니다. ssh-agent는 많은 Linux 배포판에 포함되어 있으며(보통 이미 실행 중) 설정 가능한 시간 동안 암호화되지 않은 개인 키를 메모리에 보관할 수 있게 해주는 프로그램입니다. 간단히 ssh-add를 실행하면 암호를 묻는 메시지가 표시됩니다. 설정한 시간이 지나기 전까지는 다시 암호를 묻지 않습니다.
우리는 Ed25519 키를 사용할 것입니다. https://linux-audit.com/에 따르면:
타원 곡선 서명 방식을 사용하여 ECDSA 및 DSA보다 더 나은 보안을 제공합니다. 동시에 성능도 좋습니다.
man ssh-keygenman ssh-copy-idman ssh-add서버에 연결하는 데 사용할 컴퓨터(서버 자체가 아닌 클라이언트)에서 ssh-keygen을 사용하여 Ed25519 키를 생성하세요:
ssh-keygen -t ed25519
Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519): Created directory '/home/user/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/user/.ssh/id_ed25519. Your public key has been saved in /home/user/.ssh/id_ed25519.pub. The key fingerprint is: SHA256:F44D4dr2zoHqgj0i2iVIHQ32uk/Lx4P+raayEAQjlcs user@client The key's randomart image is: +--[ED25519 256]--+ |xxxx x | |o.o +. . | | o o oo . | |. E oo . o . | | o o. o S o | |... .. o o | |.+....+ o | |+.=++o.B.. | |+..=**=o=. | +----[SHA256]-----+
참고: 암호를 설정한 경우 ssh-agent를 사용하지 않으면 이 키로 서버에 연결할 때마다 암호를 입력해야 합니다.
이제 클라이언트의 공개 키 ~/.ssh/id_ed25519.pub를 서버의 ~/.ssh/authorized_keys 파일에 추가해야 합니다. 아직 LAN에 있으므로 MIM 공격으로부터 안전할 가능성이 높으므로 ssh-copy-id를 사용하여 공개 키를 전송하고 추가하겠습니다:
ssh-copy-id user@server
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub" The authenticity of host 'host (192.168.1.96)' can't be established. ECDSA key fingerprint is SHA256:QaDQb/X0XyVlogh87sDXE7MR8YIK7ko4wS5hXjRySJE. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys user@host's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'user@host'" and check to make sure that only the key(s) you wanted were added.
이제 설정에 따른 특정 작업을 수행하기 좋은 시점입니다.
(목차)
서버에 SSH로 접속할 수 있는 사용자를 쉽게 제어하기 위해서입니다. 그룹을 사용하면 계정을 그룹에 빠르게 추가/제거하여 SSH 접속을 허용하거나 차단할 수 있습니다.
SSH 구성 파일 /etc/ssh/sshd_config에서 AllowGroups 옵션을 사용하여 SSH 서버에 특정 UNIX 그룹의 구성원만 SSH로 접속할 수 있도록 지시합니다. 그룹에 속하지 않은 사용자는 SSH로 접속할 수 없습니다.
/etc/ssh/sshd_config에서 서버에 SSH로 접속할 수 있는 사용자를 제한하는 데 사용할 UNIX 그룹/etc/ssh/sshd_config에서 설정된 AllowGroup 설정을 지원하기 위한 필수 조건입니다.man groupaddman usermod그룹을 생성하세요:
sudo groupadd sshusers
계정을 그룹에 추가하세요:
sudo usermod -a -G sshusers user1
sudo usermod -a -G sshusers user2
sudo usermod -a -G sshusers ...
서버에서 SSH 접속이 필요한 모든 계정에 대해 이 작업을 수행해야 합니다.
(목차)
/etc/ssh/sshd_config 보안 설정SSH는 서버로 들어가는 문입니다. 특히 라우터에서 포트를 열어 홈 네트워크 외부에서 서버로 SSH 접속을 허용하는 경우 더욱 그렇습니다. 제대로 보호되지 않으면 악의적인 공격자가 이를 이용하여 시스템에 무단 접근할 수 있습니다.
/etc/ssh/sshd_config는 SSH 서버가 사용하는 기본 구성 파일입니다. 이 파일을 사용하여 SSH 서버가 사용해야 하는 옵션을 지정합니다.
man sshd_configOpenSSH 서버의 구성 파일 /etc/ssh/sshd_config를 백업하고 주석을 제거하여 읽기 쉽게 만듭니다:
sudo cp --archive /etc/ssh/sshd_config /etc/ssh/sshd_config-COPY-$(date +"%Y%m%d%H%M%S")
sudo sed -i -r -e '/^#|^$/ d' /etc/ssh/sshd_config
/etc/ssh/sshd_config를 편집하고 다음 설정을 찾아 편집하거나 추가합니다. 이 설정은 구성/설정에 관계없이 적용되어야 합니다:
참고: SSH는 중복된 모순 설정을 좋아하지 않습니다. 예를 들어 ChallengeResponseAuthentication no 다음에 ChallengeResponseAuthentication yes가 있으면 SSH는 첫 번째 설정을 존중하고 두 번째 설정을 무시합니다. /etc/ssh/sshd_config 파일에 아래 설정/줄 중 일부가 이미 있을 수 있습니다. 문제를 피하려면 /etc/ssh/sshd_config 파일을 수동으로 검토하여 중복된 모순 설정을 처리해야 합니다.
참고: OpenSSH 9.1 이상을 사용하는 경우 아래 구성에서 RequiredRSASize 3072 줄의 주석 처리를 해제하세요. 이 설정은 최소 RSA 키 크기를 3072비트로 강제하며 인증 중에 더 작은 RSA 키를 거부합니다. 이는 RSA 키에만 영향을 미칩니다. ED25519 또는 ECDSA 키를 사용하는 경우 영향을 받지 않습니다. ssh-keygen -l -f ~/.ssh/id_rsa로 키 유형과 크기를 확인할 수 있습니다. 이전 OpenSSH 버전에서는 이 줄을 주석 처리된 상태로 두세요. sshd가 시작되지 않을 수 있습니다.
########################################################################################################
# start settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
########################################################################################################
# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms [email protected],ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
MACs [email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected]
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Use kernel sandbox mechanisms where possible in unprivileged processes
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
# Note: This setting is deprecated in OpenSSH 7.5 (https://www.openssh.com/txt/release-7.5)
# UsePrivilegeSeparation sandbox
########################################################################################################
# end settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
########################################################################################################
# don't let users set environment variables
PermitUserEnvironment no
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO
# disable X11 forwarding as X11 is very insecure
# you really shouldn't be running X on a server anyway
X11Forwarding no
# disable port forwarding
AllowTcpForwarding no
AllowStreamLocalForwarding no
GatewayPorts no
PermitTunnel no
# don't allow login if the account has an empty password
PermitEmptyPasswords no
# ignore .rhosts and .shosts
IgnoreRhosts yes
# verify hostname matches IP
UseDNS yes
Compression no
# TCP keepalive is spoofable (runs outside the encrypted channel)
# Use ClientAlive instead (runs inside the encrypted channel)
TCPKeepAlive no
AllowAgentForwarding no
PermitRootLogin no
# don't allow .rhosts or /etc/hosts.equiv
HostbasedAuthentication no
# OpenSSH 9.1 and later
# Enforce a minimum RSA key size of 3072 bits
# https://www.keylength.com/en/compare/
# RequiredRSASize 3072
# https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/115
HashKnownHosts yes
그런 다음 찾아 편집하거나 추가할 설정과 요구 사항에 따라 값을 설정하세요:
서로 모순되는 중복 설정이 없는지 확인하세요. 아래 명령어는 출력이 없어야 합니다.
awk 'NF && $1!~/^(#|HostKey)/{print $1}' /etc/ssh/sshd_config | sort | uniq -c | grep -v ' 1 '
ssh를 다시 시작하세요:
sudo service sshd restart
sshd -T를 사용하여 구성이 적용되었는지 확인하고 출력을 확인할 수 있습니다:
sudo sshd -T
port 22 addressfamily any listenaddress [::]:22 listenaddress 0.0.0.0:22 usepam yes logingracetime 30 x11displayoffset 10 maxauthtries 2 maxsessions 2 clientaliveinterval 15 clientalivecountmax 3 streamlocalbindmask 0177 permitrootlogin no ignorerhosts yes ignoreuserknownhosts no hostbasedauthentication no ... subsystem sftp internal-sftp -f AUTHPRIV -l INFO maxstartups 2:30:2 permittunnel no ipqos lowdelay throughput rekeylimit 0 0 permitopen any
(목차)
Mozilla의 OpenSSH 6.7+ 지침에 따르면 "사용되는 모든 Diffie-Hellman 모듈러스는 최소 3072비트 길이여야 합니다."
Diffie-Hellman 알고리즘은 SSH가 보안 연결을 설정하는 데 사용됩니다. 모듈러스(키 크기)가 클수록 암호화가 강력해집니다.
man moduliSSH 모듈리 파일 /etc/ssh/moduli를 백업하세요:
sudo cp --archive /etc/ssh/moduli /etc/ssh/moduli-COPY-$(date +"%Y%m%d%H%M%S")
짧은 모듈리를 제거하세요:
sudo awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp
sudo mv /etc/ssh/moduli.tmp /etc/ssh/moduli
(목차)
SSH는 문과 창을 위한 훌륭한 보안 경비원이지만, 여전히 악의적인 공격자가 보고 무차별 대입(brute-force)을 시도할 수 있는 눈에 보이는 문입니다. Fail2ban이 이러한 무차별 대입 시도를 모니터링하지만, 너무 안전하다는 것은 없습니다. 두 가지 요소를 요구하면 보안 계층이 하나 더 추가됩니다.
이중 인증(2FA) / 다중 인증(MFA)을 사용하면 누군가가 들어오려면 두 개의 키가 필요하므로 악의적인 공격자가 침입하기 더 어려워집니다. 두 키는 다음과 같습니다:
두 키가 모두 없으면 접속할 수 없습니다.
많은 사람들이 이 과정이 번거롭거나 귀찮다고 느낄 수 있습니다. 또한 코드를 생성하는 인증 앱에 시스템 접속이 의존적입니다.
Linux에서 PAM은 인증을 담당합니다. PAM에는 네 가지 작업이 있으며 https://en.wikipedia.org/wiki/Linux_PAM에서 자세히 확인할 수 있습니다. 이 섹션에서는 인증 작업에 대해 설명합니다.
콘솔에서 직접 또는 SSH를 통해 서버에 로그인하면 들어온 문이 PAM의 인증 작업에 요청을 보내고 PAM은 비밀번호를 묻고 확인합니다. 각 문이 사용하는 규칙을 사용자 지정할 수 있습니다. 예를 들어 콘솔에서 직접 로그인할 때와 SSH를 통해 로그인할 때 다른 규칙 세트를 설정할 수 있습니다.
이 섹션에서는 SSH를 통해 로그인할 때의 인증 규칙을 수정하여 비밀번호와 6자리 코드를 모두 요구하도록 합니다.Google의 libpam-google-authenticator PAM 모듈을 사용하여 TOTP 키를 생성하고 확인합니다. https://fastmail.blog/2016/07/22/how-totp-authenticator-apps-work/ 및 https://jemurai.com/2018/10/11/how-it-works-totp-based-mfa/ 에 TOTP 작동 방식에 대한 훌륭한 설명이 있습니다.
우리가 할 일은 서버의 SSH PAM 구성에 사용자에게 비밀번호를 입력하도록 요청한 다음 숫자 토큰을 입력하도록 지시하는 것입니다. 그러면 PAM은 사용자의 비밀번호를 확인하고, 올바르면 인증 요청을 libpam-google-authenticator로 라우팅하여 6자리 토큰을 요청하고 확인합니다. 모든 것이 정상인 경우에만 인증이 성공하고 사용자가 로그인할 수 있습니다.
libpam-google-authenticator를 설치합니다.
Debian 기반 시스템에서:
sudo apt install libpam-google-authenticator
2FA/MFA를 활성화하려는 ID로 로그인했는지 확인하고 google-authenticator를 실행하여 필요한 토큰 데이터를 생성합니다.
google-authenticator
인증 토큰을 시간 기반으로 하시겠습니까? (y/n) y https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@host%3Fsecret%3DR4ZWX34FQKZROVX7AGLJ64684Y%26issuer%3Dhost ... 새 비밀 키는 다음과 같습니다: R3NVX3FFQKZROVX7AGLJUGGESY 인증 코드는 751419입니다. 긴급 스크래치 코드는 다음과 같습니다: 12345678 90123456 78901234 56789012 34567890 "/home/user/.google_authenticator" 파일을 업데이트하시겠습니까? (y/n) y 동일한 인증 토큰의 여러 사용을 허용하지 않으시겠습니까? 이렇게 하면 약 30초마다 한 번의 로그인으로 제한되지만, 중간자 공격을 인지하거나 방지할 가능성이 높아집니다. (y/n) 동일한 인증 토큰의 여러 사용을 허용하지 않으시겠습니까? 이렇게 하면 약 30초마다 한 번의 로그인으로 제한되지만, 중간자 공격을 인지하거나 방지할 가능성이 높아집니다. (y/n) y 기본적으로 토큰은 30초 동안 유효합니다. 클라이언트와 서버 간의 시간 차이를 보정하기 위해 현재 시간 전후에 추가 토큰을 허용합니다. 시간 동기화가 좋지 않은 문제가 발생하면 기본 크기인 +-1분(윈도우 크기 3)에서 약 +-4분(윈도우 크기 17개의 허용 가능한 토큰)으로 늘릴 수 있습니다. 그렇게 하시겠습니까? (y/n) y 로그인하려는 컴퓨터가 무차별 대입 로그인 시도에 대해 강화되지 않은 경우, 인증 모듈에 대한 속도 제한을 활성화할 수 있습니다. 기본적으로 이는 공격자를 30초당 3회 이하의 로그인 시도로 제한합니다. 속도 제한을 활성화하시겠습니까? (y/n) y
이것은 루트가 아닌 상태에서 실행된다는 점에 유의하세요.
모든 질문에 기본 옵션(대부분 y)을 선택하고 긴급 스크래치 코드를 저장하는 것을 잊지 마세요.
PAM의 SSH 구성 파일 /etc/pam.d/sshd의 백업을 만듭니다:
sudo cp --archive /etc/pam.d/sshd /etc/pam.d/sshd-COPY-$(date +"%Y%m%d%H%M%S")
이제 SSH에 대한 인증 방법으로 활성화하기 위해 /etc/pam.d/sshd에 다음 줄을 추가합니다:
auth required pam_google_authenticator.so nullok
참고: nullok의 의미는 여기를 확인하세요.
echo -e "\nauth required pam_google_authenticator.so nullok # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 추가" | sudo tee -a /etc/pam.d/sshd
SSH가 이를 활용하도록 /etc/ssh/sshd_config에서 다음 줄을 추가하거나 편집합니다:
ChallengeResponseAuthentication yes
sudo sed -i -r -e "s/^(challengeresponseauthentication .*)$/# \1 # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 주석 처리/I" /etc/ssh/sshd_config
echo -e "\nChallengeResponseAuthentication yes # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 추가" | sudo tee -a /etc/ssh/sshd_config
ssh를 다시 시작합니다:
sudo service sshd restart
(목차)
sudo는 계정이 루트를 포함한 다른 계정으로 명령을 실행할 수 있게 합니다. 원하는 계정만 sudo를 사용할 수 있도록 해야 합니다.
Debian은 sudo 그룹을 생성합니다. 이 그룹의 구성원(sudo 권한이 있는 사용자)을 보려면:
cat /etc/group | grep "sudo"
RedHat은 wheel 그룹을 생성합니다.
sudo가 비밀번호를 요구하지 않도록 설정하는 경우에 대한 참고 사항은 https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/39를 확인하세요. 공유해 주신 sbrl 님께 감사드립니다.그룹을 만듭니다:
sudo groupadd sudousers
그룹에 계정을 추가합니다:
sudo usermod -a -G sudousers user1
sudo usermod -a -G sudousers user2
sudo usermod -a -G sudousers ...
sudo 권한이 필요한 서버의 모든 계정에 대해 이 작업을 수행해야 합니다.
sudo의 구성 파일 /etc/sudoers의 백업을 만듭니다:
sudo cp --archive /etc/sudoers /etc/sudoers-COPY-$(date +"%Y%m%d%H%M%S")
sudo의 구성 파일 /etc/sudoers를 편집합니다:
sudo visudo
아직 없는 경우 다음 줄을 추가하여 sudo가 sudousers 그룹의 사용자만 sudo를 사용하도록 지시합니다:
%sudousers ALL=(ALL:ALL) ALL
(목차)
su 또한 계정이 루트를 포함한 다른 계정으로 명령을 실행할 수 있게 합니다. 원하는 계정만 su를 사용할 수 있도록 해야 합니다.
그룹을 만듭니다:
sudo groupadd suusers
그룹에 계정을 추가합니다:
sudo usermod -a -G suusers user1
sudo usermod -a -G suusers user2
sudo usermod -a -G suusers ...
sudo 권한이 필요한 서버의 모든 계정에 대해 이 작업을 수행해야 합니다.
이 그룹의 사용자만 /bin/su를 실행할 수 있도록 설정합니다:
sudo dpkg-statoverride --update --add root suusers 4750 /bin/su
(목차)
많은 애플리케이션을 샌드박스에서 실행하는 것이 훨씬 더 좋습니다.
브라우저(특히 클로즈드 소스 브라우저)와 이메일 클라이언트는 매우 권장됩니다.
소프트웨어를 설치합니다:
sudo apt install firejail firejail-profiles
참고: Debian 10 Stable의 경우 공식 백포트가 권장됩니다:
sudo apt install -t buster-backports firejail firejail-profiles
애플리케이션(/usr/bin 또는 /bin에 설치됨)이 샌드박스에서만 실행되도록 허용합니다(아래 몇 가지 예 참조):
sudo ln -s /usr/bin/firejail /usr/local/bin/google-chrome-stable
sudo ln -s /usr/bin/firejail /usr/local/bin/firefox
sudo ln -s /usr/bin/firejail /usr/local/bin/chromium
sudo ln -s /usr/bin/firejail /usr/local/bin/evolution
sudo ln -s /usr/bin/firejail /usr/local/bin/thunderbird
평소처럼 애플리케이션을 실행하고(터미널 또는 실행기를 통해) 감옥에서 실행 중인지 확인합니다:
firejail --list
샌드박스 처리된 앱을 이전처럼 다시 실행할 수 있도록 허용합니다(예: firefox):
sudo rm /usr/local/bin/firefox
(목차)
많은 보안 프로토콜이 시간을 활용합니다. 시스템 시간이 정확하지 않으면 서버에 부정적인 영향을 미칠 수 있습니다. NTP 클라이언트는 글로벌 NTP 서버와 시스템 시간을 동기화하여 이 문제를 해결할 수 있습니다.
NTP는 Network Time Protocol의 약자입니다. 이 가이드의 맥락에서 서버의 NTP 클라이언트는 공식 서버에서 가져온 공식 시간으로 서버 시간을 업데이트하는 데 사용됩니다. 모든 공용 NTP 서버는 https://www.pool.ntp.org/en/ 에서 확인하세요.
참고: **Debian 13 (Trixie)**부터 기존
ntp패키지가 제거되었습니다.sudo apt install ntp를 실행하면 "Package ntp has no installation candidate" 오류가 발생합니다. 이 가이드는 NTP를 클라이언트(서버 시계 동기화)로만 사용하므로, Debian 13+에서 권장되는 방법은 추가 패키지가 필요 없으며 이미 사전 설치된systemd-timesyncd를 사용하는 것입니다. 아래 Debian 13+ 단계를 참조하세요.
systemd-timesyncd는 Debian에 이미 포함된 경량 SNTP 클라이언트입니다. 전체 ntpd 데몬과 달리 어떤 포트도 수신하지 않으므로 공격 표면이 더 작습니다. 이 가이드의 목적(서버 시계 동기화 유지)에는 이것만으로 충분합니다.
NTP 동기화를 활성화합니다:
sudo timedatectl set-ntp true
작동 중인지 확인합니다:
timedatectl status
출력에 NTP service: active 및 System clock synchronized: yes가 표시되어야 합니다.
신뢰할 수 있는 NTP 서버를 구성합니다. 구성 파일의 백업을 만든 다음 편집합니다:
sudo cp --archive /etc/systemd/timesyncd.conf /etc/systemd/timesyncd.conf-COPY-$(date +"%Y%m%d%H%M%S")
/etc/systemd/timesyncd.conf를 편집하고 [Time] 섹션의 주석을 해제/설정합니다:
[Time]
NTP=pool.ntp.org
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org
sudo sed -i -r -e "s/^#?NTP=.*$/NTP=pool.ntp.org # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 추가/" /etc/systemd/timesyncd.conf
sudo sed -i -r -e "s/^#?FallbackNTP=.*$/FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 추가/" /etc/systemd/timesyncd.conf
변경 사항을 적용하려면 서비스를 다시 시작합니다:
sudo systemctl restart systemd-timesyncd
동기화 상태를 확인합니다:
timedatectl timesync-status
Server: 108.61.56.35 (pool.ntp.org) Poll interval: 32s (min: 32s; max: 34min 8s) Leap: normal Version: 4 Stratum: 2 Reference: C342F10A Precision: 1us (2^0) Root distance: 24.054ms (max: 5s) Offset: +2.156ms Delay: 48.567ms Jitter: 1.452ms Packet count: 3
참고: 이 단계는 Debian 12 및 이전 버전에만 적용됩니다. Debian 13+에서는
ntp패키지를 더 이상 사용할 수 없습니다. 대신 위의 systemd-timesyncd 단계를 사용하세요.
ntp를 설치합니다.
Debian 기반 시스템에서:
sudo apt install ntp
NTP 클라이언트의 구성 파일 /etc/ntp.conf의 백업을 만듭니다:
sudo cp --archive /etc/ntp.conf /etc/ntp.conf-COPY-$(date +"%Y%m%d%H%M%S")
적어도 Debian의 기본 구성은 이미 상당히 안전합니다. 유일한 확인 사항은 server 지시어가 아닌 pool 지시어를 사용하는지 확인하는 것입니다. pool 지시어는 NTP 클라이언트가 응답하지 않거나 잘못된 시간을 제공하는 서버를 중단할 수 있게 합니다. /etc/ntp.conf에서 모든 server 지시어를 주석 처리하고 아래 내용을 추가하여 이 작업을 수행합니다.
pool pool.ntp.org iburst
sudo sed -i -r -e "s/^((server|pool).*)/# \1 # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 주석 처리/" /etc/ntp.conf
echo -e "\npool pool.ntp.org iburst # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 추가" | sudo tee -a /etc/ntp.conf
예시 /etc/ntp.conf:
driftfile /var/lib/ntp/ntp.drift statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable restrict -4 default kod notrap nomodify nopeer noquery limited restrict -6 default kod notrap nomodify nopeer noquery limited restrict 127.0.0.1 restrict ::1 restrict source notrap nomodify noquery pool pool.ntp.org iburst # 사용자가 2019-03-09 @ 10:23:35에 추가
ntp를 다시 시작합니다:
sudo service ntp restart
ntp 서비스의 상태를 확인합니다:
sudo systemctl status ntp
● ntp.service - LSB: Start NTP daemon Loaded: loaded (/etc/init.d/ntp; generated; vendor preset: enabled) Active: active (running) since Sat 2019-03-09 15:19:46 EST; 4s ago Docs: man:systemd-sysv-generator(8) Process: 1016 ExecStop=/etc/init.d/ntp stop (code=exited, status=0/SUCCESS) Process: 1028 ExecStart=/etc/init.d/ntp start (code=exited, status=0/SUCCESS) Tasks: 2 (limit: 4915) CGroup: /system.slice/ntp.service └─1038 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 108:113 Mar 09 15:19:46 host ntpd[1038]: Listen and drop on 0 v6wildcard [::]:123 Mar 09 15:19:46 host ntpd[1038]: Listen and drop on 1 v4wildcard 0.0.0.0:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 2 lo 127.0.0.1:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 3 enp0s3 10.10.20.96:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 4 lo [::1]:123 Mar 09 15:19:46 host ntpd[1038]: Listen normally on 5 enp0s3 [fe80::a00:27ff:feb6:ed8e%2]:123 Mar 09 15:19:46 host ntpd[1038]: Listening on routing socket on fd #22 for interface updates Mar 09 15:19:47 host ntpd[1038]: Soliciting pool server 108.61.56.35 Mar 09 15:19:48 host ntpd[1038]: Soliciting pool server 69.89.207.199 Mar 09 15:19:49 host ntpd[1038]: Soliciting pool server 45.79.111.114
ntp의 상태를 확인합니다:
sudo ntpq -p
remote refid st t when poll reach delay offset jitter ============================================================================== pool.ntp.org .POOL. 16 p - 64 0 0.000 0.000 0.000 *lithium.constan 198.30.92.2 2 u - 64 1 19.900 4.894 3.951 ntp2.wiktel.com 212.215.1.157 2 u 2 64 1 48.061 -0.431 0.104
(목차)
/proc을 살펴보면 많은 파일과 디렉토리를 발견할 수 있습니다. 그 중 대부분은 숫자일 뿐이며, 특정 프로세스 ID(PID)에 대한 정보를 나타냅니다. 기본적으로 Linux 시스템은 모든 로컬 사용자가 이 모든 정보를 볼 수 있도록 배포됩니다. 여기에는 다른 사용자의 프로세스 정보도 포함됩니다. 여기에는 다른 사용자와 공유하고 싶지 않은 민감한 세부 정보가 포함될 수 있습니다. 일부 파일 시스템 구성 조정을 적용하여 이 동작을 변경하고 시스템의 보안을 향상시킬 수 있습니다.
참고: 일부 systemd 시스템에서 작동하지 않을 수 있습니다. 자세한 내용은 https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/37를 확인하세요. 공유해 주신 nlgranger 님께 감사드립니다.
/proc을 hidepid=2로 마운트하여 사용자가 자신의 프로세스에 대한 정보만 볼 수 있도록 함/etc/fstab의 백업을 만듭니다:
sudo cp --archive /etc/fstab /etc/fstab-COPY-$(date +"%Y%m%d%H%M%S")
/proc이 hidepid=2로 마운트되도록 /etc/fstab에 다음 줄을 추가합니다:
proc /proc proc defaults,hidepid=2 0 0
echo -e "\nproc /proc proc defaults,hidepid=2 0 0 # $(whoami) 님이 $(date +"%Y-%m-%d @ %H:%M:%S")에 추가" | sudo tee -a /etc/fstab
시스템을 재부팅합니다:
sudo reboot now
참고: 또는 재부팅하지 않고 sudo mount -o remount,hidepid=2 /proc로 /proc을 다시 마운트할 수 있습니다.
(목차)
기본적으로 계정은 나쁜 비밀번호를 포함하여 원하는 모든 비밀번호를 사용할 수 있습니다. pwquality/pam_pwquality는 "시스템 비밀번호의 기본 비밀번호 품질 요구 사항을 구성하는 방법"을 제공하고 "시스템 사전과 약한 선택을 식별하기 위한 규칙 집합에 대해 강도를 확인"하여 이 보안 격차를 해결합니다.
Linux에서 PAM은 인증을 담당합니다. PAM에는 https://en.wikipedia.org/wiki/Linux_PAM 에서 읽을 수 있는 네 가지 작업이 있습니다. 이 섹션에서는 비밀번호 작업에 대해 설명합니다.계정 비밀번호를 설정하거나 변경해야 할 때, PAM의 비밀번호 작업이 요청을 처리합니다. 이 섹션에서는 PAM의 비밀번호 작업이 요청된 새 비밀번호를 libpam-pwquality에 전달하여 요구 사항을 충족하는지 확인하도록 지시합니다. 요구 사항이 충족되면 비밀번호가 사용/설정되고, 충족되지 않으면 오류가 발생하고 사용자에게 알립니다.
libpam-pwquality를 설치합니다.
Debian 기반 시스템에서:
sudo apt install libpam-pwquality
PAM의 비밀번호 구성 파일 /etc/pam.d/common-password를 백업합니다:
sudo cp --archive /etc/pam.d/common-password /etc/pam.d/common-password-COPY-$(date +"%Y%m%d%H%M%S")
파일 /etc/pam.d/common-password를 편집하여 PAM이 libpam-pwquality를 사용하여 강력한 비밀번호를 강제하도록 지시하고, 다음과 같이 시작하는 줄을 변경합니다:
password requisite pam_pwquality.so
를 다음과 같이 변경합니다:
password requisite pam_pwquality.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec
위 옵션은 다음과 같습니다:
retry=3 = 오류를 반환하기 전에 사용자에게 3번 입력을 요청합니다.minlen=10 = 다음 항목의 크레딧(또는 차감)을 고려한 비밀번호의 최소 길이:
dcredit=-1 = 최소 한 개의 숫자가 있어야 함ucredit=-1 = 최소 한 개의 대문자가 있어야 함lcredit=-1 = 최소 한 개의 소문자가 있어야 함ocredit=-1 = 최소 한 개의 비알파벳 문자가 있어야 함difok=3 = 새 비밀번호에서 이전 비밀번호에 없어야 하는 최소 문자 수 3개maxrepeat=3 = 최대 3개의 반복 문자 허용gecoschec = 계정 이름이 포함된 비밀번호를 허용하지 않음sudo sed -i -r -e "s/^(password\s+requisite\s+pam_pwquality.so)(.*)$/# \1\2 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")\n\1 retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 maxrepeat=3 gecoschec # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/" /etc/pam.d/common-password
(목차)
서버를 최신 중요 보안 패치 및 업데이트로 유지하는 것이 중요합니다. 그렇지 않으면 나쁜 행위자가 서버에 무단 액세스하는 데 사용할 수 있는 알려진 보안 취약성에 노출될 위험이 있습니다.
매일 서버를 확인할 계획이 없다면, 시스템을 자동으로 업데이트하거나 사용 가능한 업데이트에 대한 이메일을 받을 방법을 원할 것입니다.
모든 업데이트를 수행하는 것은 위험할 수 있으므로 바람직하지 않습니다. 중요한 업데이트를 수행하는 것이 중요하지만, 나머지는 수동으로 수행할 시간이 있을 때까지 기다릴 수 있습니다.
자동 및 무인 업데이트는 시스템을 손상시킬 수 있으며, 서버 근처에 없어서 수리하지 못할 수 있습니다. SSH 액세스가 손상되면 특히 문제가 됩니다.
Debian 기반 시스템에서 다음을 사용할 수 있습니다:
unattended-upgrades를 사용하여 중요 보안 패치를 적용합니다. Debian 커뮤니티에서 이미 철저히 테스트되었으므로 안정적인 업데이트도 적용할 수 있습니다.
/etc/apt/apt.conf.d/50unattended-upgradesunattended-upgrades, apt-listchanges, apticron을 설치합니다:
sudo apt install unattended-upgrades apt-listchanges apticron
이제 unattended-upgrades를 구성하여 업데이트를 자동으로 적용해야 합니다. 일반적으로 패키지에서 생성된 /etc/apt/apt.conf.d/20auto-upgrades 및 /etc/apt/apt.conf.d/50unattended-upgrades 파일을 편집하여 수행합니다. 그러나 이러한 파일은 향후 업데이트에서 덮어쓸 수 있으므로 대신 새 파일을 생성하겠습니다. /etc/apt/apt.conf.d/51myunattended-upgrades 파일을 만들고 다음을 추가합니다:
// Enable the update/upgrade script (0=disable)
APT::Periodic::Enable "1";
// Do "apt-get update" automatically every n-days (0=disable)
APT::Periodic::Update-Package-Lists "1";
// Do "apt-get upgrade --download-only" every n-days (0=disable)
APT::Periodic::Download-Upgradeable-Packages "1";
// Do "apt-get autoclean" every n-days (0=disable)
APT::Periodic::AutocleanInterval "7";
// Send report mail to root
// 0: no report (or null string)
// 1: progress report (actually any string)
// 2: + command outputs (remove -qq, remove 2>/dev/null, add -d)
// 3: + trace on APT::Periodic::Verbose "2";
APT::Periodic::Unattended-Upgrade "1";
// Automatically upgrade packages from these
Unattended-Upgrade::Origins-Pattern {
"o=Debian,a=stable";
"o=Debian,a=stable-updates";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
};
// You can specify your own packages to NOT automatically upgrade here
Unattended-Upgrade::Package-Blacklist {
};
// Run dpkg --force-confold --configure -a if a unclean dpkg state is detected to true to ensure that updates get installed even when the system got interrupted during a previous run
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
//Perform the upgrade when the machine is running because we wont be shutting our server down often
Unattended-Upgrade::InstallOnShutdown "false";
// Send an email to this address with information about the packages upgraded.
Unattended-Upgrade::Mail "root";
// Always send an e-mail
Unattended-Upgrade::MailOnlyOnError "false";
// Remove all unused dependencies after the upgrade has finished
Unattended-Upgrade::Remove-Unused-Dependencies "true";
// Remove any new unused dependencies after the upgrade has finished
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
// Automatically reboot WITHOUT CONFIRMATION if the file /var/run/reboot-required is found after the upgrade.
Unattended-Upgrade::Automatic-Reboot "true";
// Automatically reboot even if users are logged in.
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
참고:
/usr/lib/apt/apt.systemd.daily에서 APT::Periodic 옵션에 대한 세부 정보를 확인하세요.Unattended-Upgrade 옵션에 대한 세부 정보를 확인하세요.구성 파일이 올바른지 확인하기 위해 unattended-upgrades의 dry-run을 실행합니다:
sudo unattended-upgrade -d --dry-run
모든 것이 정상이면 예약된 시간에 실행하거나 unattended-upgrade -d로 강제 실행할 수 있습니다.
apt-listchanges를 원하는 대로 구성합니다:
sudo dpkg-reconfigure apt-listchanges
apticron의 경우 기본 설정으로 충분하지만 변경하려면 /etc/apticron/apticron.conf에서 확인할 수 있습니다. 예를 들어, 내 구성은 다음과 같습니다:
EMAIL="root" NOTIFY_NO_UPDATES="1"
(목차)
WIP
WIP
WIP
rng-tools를 설치합니다.
Debian 기반 시스템에서:
sudo apt-get install rng-tools
이제 /etc/default/rng-tools에 다음을 추가하여 난수 생성에 사용되는 하드웨어 장치를 설정해야 합니다:
HRNGDEVICE=/dev/urandom
echo "HRNGDEVICE=/dev/urandom" | sudo tee -a /etc/default/rng-tools
서비스를 다시 시작합니다:
sudo systemctl stop rng-tools.service
sudo systemctl start rng-tools.service
난수성 테스트:
(목차)
물리적 공격(직접, 갈취/강도/폭행 방법)에 대비하여 추가 비밀번호 보안을 제공하는 좋은 도구입니다.
pamduress는 X 사용자에게 보조 비밀번호(패닉 비밀번호)를 추가합니다. 이 비밀번호가 일치하면 스크립트가 실행됩니다(이 스크립트는 사용자가 이 패닉 비밀번호로 로그인할 때 사용자가 원하는 작업을 수행합니다).
실제 사례: "강도가 집에 침입하여 서버(중요한 비즈니스 백업, 개인 추억 등을 포함)를 훔쳤습니다. 디스크/부트 암호화가 없습니다. 강도가 '안전한 장소'에서 서버를 시작하고 무차별 대입 공격을 시작했습니다. sudoer 'admin' 사용자의 SSH 로컬 비밀번호를 크랙했습니다. 예, 강력하지 않은 비밀번호입니다. 강도는 이 크랙된 더미/패닉 비밀번호로 sudoer 'admin'으로 SSH 세션(또는 물리적 세션)을 시작했습니다. 서버가 2분도 안 되어 너무 바빠져서 결국 멈추는 것을 느꼈습니다.. '뭐야?! 재부팅하고 정보를 계속 훔쳐야겠다'.. 죄송합니다. 모든 데이터와 시스템이 파괴되었습니다." 결론적으로, 강도가 더미/패닉/보조 비밀번호를 크랙했고, 이 비밀번호와 연결된 스크립트가 모든 파일, 구성, 시스템, 부트를 삭제한 후 RAM과 CPU를 사용하여 강도가 시스템을 재부팅하도록 강제합니다.
강제적인 방법(폭행, 총기, 갈취 등)으로 비밀번호를 얻은 악의적인 사람이 서버 정보에 액세스하는 것을 방지합니다. 물론 다른 상황에서도 유용합니다.
cat > "$ScriptFile" <<-EOF #!/bin/bash sudo rm -rf /home
EOF ####################################################### } echo "Lets Config a PANIC PASSWORD ;)" && sleep 1 read -r -p "Want you REALLY configure A PANIC PASSWORD?? Write [ OK ] : " PAMDUR if [[ "$PAMDUR" = "OK" ]]; then echo "Lets Config a PANIC USER, PASSWORD and SCRIPT ;)" && sleep 1 while [ -z "$PANICUSR" ] do read -r -p "WRITE a Panic User to your pam-duress user [ root ]: " PANICUSR PANICUSR=${PANICUSR:=root} done if [ -z "$ScriptLoc" ]; then read -r -p "SET Script Directory with FULL PATH [ /root/.duress ]: " ScriptLoc ScriptLoc=${ScriptLoc:=/root/.duress} ScriptFile="$ScriptLoc/PanicScript.sh" fi else echo "NOT Use PAM DURESS aKa Panic Password!!! Bye" exit 1 fi
sudo apt install -y git build-essential libpam0g-dev libssl-dev
cd "$HOME" || exit 1 git clone https://github.com/nuvious/pam-duress.git cd pam-duress || exit 1 make sudo make install make clean #make uninstall
mkdir -p $ScriptLoc sudo mkdir -p /etc/duress.d myownscript duress_sign $ScriptFile chmod -R 500 $ScriptLoc chmod 400 $ScriptLoc/*.sha256 chown -R $PANICUSR $ScriptLoc
sudo cp --preserve /etc/pam.d/common-auth /etc/pam.d/common-auth.bck
echo " auth [success=2 default=ignore] pam_unix.so nullok_secure auth [success=1 default=ignore] pam_duress.so auth requisite pam_deny.so auth required pam_permit.so " | sudo tee /etc/pam.d/common-auth
read -r -p "Press Key to Finish PAM DURESS Script!" exit 0
([Table of Contents](#table-of-contents))
## 네트워크
### UFW(Uncomplicated Firewall)를 사용한 방화벽
#### 왜 필요한가
편집증적이라고 생각하셔도 좋고 동의하지 않으셔도 됩니다. 하지만 저는 명시적으로 허용한 트래픽을 제외하고 서버의 모든 인바운드 및 아웃바운드 트래픽을 차단하고 싶습니다. 내가 모르는 트래픽을 서버가 왜 외부로 보내야 할까요? 그리고 내가 누군지, 무엇인지 모르는 외부 트래픽이 왜 내 서버에 접근하려 할까요? 좋은 보안에 관해 제 의견은 기본적으로 거부/차단하고 예외적으로 허용하는 것입니다.
물론 동의하지 않으셔도 전혀 문제없으며 필요에 맞게 UFW를 구성하시면 됩니다.
어느 쪽이든, 명시적으로 허용한 트래픽만 허용되도록 하는 것이 방화벽의 역할입니다.
#### 작동 방식
Linux 커널은 네트워크 트래픽을 모니터링하고 제어하는 기능을 제공합니다. 이러한 기능은 방화벽 유틸리티를 통해 최종 사용자에게 제공됩니다. Linux에서 가장 일반적인 방화벽은 [iptables](https://en.wikipedia.org/wiki/Iptables)입니다. 하지만 iptables는 상당히 복잡하고 혼란스럽습니다(IMHO). 이때 UFW가 등장합니다. UFW를 iptables의 프론트엔드로 생각하세요. 네트워크 트래픽을 어떻게 처리할지 Linux 커널에 지시하는 iptables 규칙을 관리하는 과정을 단순화합니다.
**UFW**는 다음과 같은 규칙을 구성할 수 있게 해줍니다:
- **허용** 또는 **차단**
- **인바운드** 또는 **아웃바운드** 트래픽
- 포트 **대상** 또는 **출발지**
포트를 명시적으로 지정하거나 포트를 지정하는 애플리케이션 구성을 통해 규칙을 만들 수 있습니다.
#### 목표
- 명시적으로 허용한 트래픽을 제외한 모든 인바운드 및 아웃바운드 네트워크 트래픽 차단
#### 참고 사항
- 다른 프로그램을 설치할 때 필요한 포트/애플리케이션을 활성화해야 합니다.
#### 참고 자료
- https://launchpad.net/ufw
#### 단계
1. ufw를 설치합니다.
Debian 기반 시스템의 경우:
``` bash
sudo apt install ufw
```
1. 모든 아웃바운드 트래픽을 차단합니다:
``` bash
sudo ufw default deny outgoing comment 'deny all outgoing traffic'
```
> ```
> 기본 아웃바운드 정책이 '차단'으로 변경되었습니다.
> (그에 따라 규칙을 업데이트하세요)
> ```
저처럼 편집증적이지 않고 모든 아웃바운드 트래픽을 차단하고 싶지 않다면 대신 허용할 수 있습니다:
``` bash
sudo ufw default allow outgoing comment 'allow all outgoing traffic'
```
1. 모든 인바운드 트래픽을 차단합니다:
``` bash
sudo ufw default deny incoming comment 'deny all incoming traffic'
```
1. 당연히 SSH 연결은 허용해야 합니다. allow 대신 limit을 사용하면 30초 이내에 6회 이상 연결을 시도하는 IP 주소의 연결을 자동으로 차단합니다:
``` bash
sudo ufw limit in ssh comment 'allow SSH connections in'
```
> ```
> 규칙이 업데이트되었습니다
> 규칙이 업데이트되었습니다 (v6)
> ```
1. 필요에 따라 추가 트래픽을 허용합니다. 몇 가지 일반적인 사용 사례:
``` bash
# allow traffic out to port 53 -- DNS
sudo ufw allow out 53 comment 'allow DNS calls out'
# allow traffic out to port 123 -- NTP
sudo ufw allow out 123 comment 'allow NTP out'
# allow traffic out for HTTP, HTTPS, or FTP
# apt might needs these depending on which sources you're using
sudo ufw allow out http comment 'allow HTTP traffic out'
sudo ufw allow out https comment 'allow HTTPS traffic out'
sudo ufw allow out ftp comment 'allow FTP traffic out'
# allow whois
sudo ufw allow out whois comment 'allow whois'
# allow mails for status notifications -- choose port according to your provider
sudo ufw allow out 25 comment 'allow SMTP out'
sudo ufw allow out 587 comment 'allow SMTP out'
# allow traffic out to port 68 -- the DHCP client
# you only need this if you're using DHCP
sudo ufw allow out 67 comment 'allow the DHCP client to update'
sudo ufw allow out 68 comment 'allow the DHCP client to update'
```
**참고**: 패키지 설치 등 여러 작업을 위해 HTTP/HTTPS를 허용해야 합니다.
1. ufw를 시작합니다:
``` bash
sudo ufw enable
```
> ```
> 명령이 기존 SSH 연결을 중단시킬 수 있습니다. 작업을 계속하시겠습니까 (y|n)? y
> 방화벽이 활성화되었으며 시스템 시작 시 사용 설정되었습니다.
> ```
1. 상태를 확인하려면:
``` bash
sudo ufw status
```
> ```
> 상태: 활성
>
> 대상 작업 출발지
> -- ------ ----
> 22/tcp LIMIT Anywhere # SSH 연결 허용
> 22/tcp (v6) LIMIT Anywhere (v6) # SSH 연결 허용
>
> 53 ALLOW OUT Anywhere # DNS 호출 허용
> 123 ALLOW OUT Anywhere # NTP 허용
> 80/tcp ALLOW OUT Anywhere # HTTP 트래픽 허용
> 443/tcp ALLOW OUT Anywhere # HTTPS 트래픽 허용
> 21/tcp ALLOW OUT Anywhere # FTP 트래픽 허용
> Mail submission ALLOW OUT Anywhere # 메일 발송 허용
> 43/tcp ALLOW OUT Anywhere # whois 허용
> 53 (v6) ALLOW OUT Anywhere (v6) # DNS 호출 허용
> 123 (v6) ALLOW OUT Anywhere (v6) # NTP 허용
> 80/tcp (v6) ALLOW OUT Anywhere (v6) # HTTP 트래픽 허용
> 443/tcp (v6) ALLOW OUT Anywhere (v6) # HTTPS 트래픽 허용
> 21/tcp (v6) ALLOW OUT Anywhere (v6) # FTP 트래픽 허용
> Mail submission (v6) ALLOW OUT Anywhere (v6) # 메일 발송 허용
> 43/tcp (v6) ALLOW OUT Anywhere (v6) # whois 허용
> ```
또는
``` bash
sudo ufw status verbose
```
> ```
> 상태: 활성
> 로깅: 켜짐 (낮음)
> 기본: 차단 (인바운드), 차단 (아웃바운드), 비활성화 (라우팅)
> 새 프로필: 건너뛰기
>
> 대상 작업 출발지
> -- ------ ----
> 22/tcp LIMIT IN Anywhere # SSH 연결 허용
> 22/tcp (v6) LIMIT IN Anywhere (v6) # SSH 연결 허용
>
> 53 ALLOW OUT Anywhere # DNS 호출 허용
> 123 ALLOW OUT Anywhere # NTP 허용
> 80/tcp ALLOW OUT Anywhere # HTTP 트래픽 허용
> 443/tcp ALLOW OUT Anywhere # HTTPS 트래픽 허용
> 21/tcp ALLOW OUT Anywhere # FTP 트래픽 허용
> 587/tcp (Mail submission) ALLOW OUT Anywhere # 메일 발송 허용
> 43/tcp ALLOW OUT Anywhere # whois 허용
> 53 (v6) ALLOW OUT Anywhere (v6) # DNS 호출 허용
> 123 (v6) ALLOW OUT Anywhere (v6) # NTP 허용
> 80/tcp (v6) ALLOW OUT Anywhere (v6) # HTTP 트래픽 허용
> 443/tcp (v6) ALLOW OUT Anywhere (v6) # HTTPS 트래픽 허용
> 21/tcp (v6) ALLOW OUT Anywhere (v6) # FTP 트래픽 허용
> 587/tcp (Mail submission (v6)) ALLOW OUT Anywhere (v6) # 메일 발송 허용
> 43/tcp (v6) ALLOW OUT Anywhere (v6) # whois 허용
> ```
7. 규칙을 삭제해야 하는 경우
``` bash
sudo ufw status numbered
[...]
sudo ufw delete 3 #line number of the rule you want to delete
```
#### 기본 애플리케이션
ufw에는 몇 가지 기본 애플리케이션이 포함되어 있습니다. 다음 명령으로 확인할 수 있습니다:``` bash
sudo ufw app list
```
> ```
> Available applications:
> AIM
> Bonjour
> CIFS
> DNS
> Deluge
> IMAP
> IMAPS
> IPP
> KTorrent
> Kerberos Admin
> Kerberos Full
> Kerberos KDC
> Kerberos Password
> LDAP
> LDAPS
> LPD
> MSN
> MSN SSL
> Mail submission
> NFS
> OpenSSH
> POP3
> POP3S
> PeopleNearby
> SMTP
> SSH
> Socks
> Telnet
> Transmission
> Transparent Proxy
> VNC
> WWW
> WWW Cache
> WWW Full
> WWW Secure
> XMPP
> Yahoo
> qBittorrent
> svnserve
> ```
앱에 대한 자세한 정보(예: 포함된 포트)를 확인하려면 다음을 입력하세요.``` bash
sudo ufw app info [app name]
```
> ``` bash
> sudo ufw app info DNS
> ```
>
> ```
> Profile: DNS
> Title: Internet Domain Name Server
> Description: Internet Domain Name Server
>
> Port:
> 53
> ```
#### 사용자 정의 애플리케이션
포트 번호를 명시적으로 제공하여 규칙을 만들고 싶지 않다면, 자신만의 애플리케이션 구성을 생성할 수 있습니다. 이를 위해 `/etc/ufw/applications.d`에 파일을 만드십시오.
예를 들어, [Plex](https://support.plex.tv/articles/201543147-what-network-ports-do-i-need-to-allow-through-my-firewall/)에 대해 사용할 내용은 다음과 같습니다:``` bash
cat /etc/ufw/applications.d/plexmediaserver
```
> ```
> [PlexMediaServer]
> title=Plex Media Server
> description=This opens up PlexMediaServer for http (32400), upnp, and autodiscovery.
> ports=32469/tcp|32413/udp|1900/udp|32400/tcp|32412/udp|32410/udp|32414/udp|32400/udp
> ```
그런 다음 다른 앱과 마찬가지로 활성화할 수 있습니다:```bash
sudo ufw allow plexmediaserver
```
([Table of Contents](#table-of-contents))
### iptables 침입 탐지 및 방지 (PSAD 사용)
#### 이유
방화벽으로 문을 보호하고 있더라도, 보호된 문 중 하나를 무차별 대입(brute-force)으로 통과하려는 시도가 있을 수 있습니다. 잠재적인 침입 시도(예: 반복된 접속 시도)를 탐지하고 차단하기 위해 모든 네트워크 활동을 모니터링하려고 합니다.
#### 작동 원리
https://serverfault.com/의 사용자 [FINESEC](https://serverfault.com/users/143961/finesec)이 https://serverfault.com/a/447604/289829에서 설명한 것보다 더 잘 설명할 수 없습니다.
> Fail2BAN은 아파치, SSH 또는 FTP와 같은 다양한 애플리케이션의 로그 파일을 스캔하고 자동 로그인 시도와 같은 악성 징후를 보이는 IP를 자동으로 차단합니다. 반면 PSAD는 iptables 및 ip6tables 로그 메시지(일반적으로 /var/log/messages)를 스캔하여 스캔, DDoS, OS 지문 수집 시도 등 기타 의심스러운 트래픽을 탐지하고 선택적으로 차단합니다. 두 프로그램은 서로 다른 수준에서 작동하므로 동시에 사용해도 괜찮습니다.
그리고 이미 [UFW](#ufw-uncomplicated-firewall)를 사용하고 있으므로 [netson](https://gist.github.com/netson)의 훌륭한 지침(https://gist.github.com/netson/c45b2dc4e835761fbccc)을 따라 PSAD를 UFW와 함께 작동하도록 설정하겠습니다.
#### 참고 자료
- http://www.cipherdyne.org/psad/
- http://www.cipherdyne.org/psad/docs/config.html
- https://www.thefanclub.co.za/how-to/how-install-psad-intrusion-detection-ubuntu-1204-lts-server
- https://serverfault.com/a/447604/289829
- https://serverfault.com/a/770424/289829
- https://gist.github.com/netson/c45b2dc4e835761fbccc
- `psadwatchd` 관련 문제([#61](https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/61))를 발견해 주신 [moltenbit](https://github.com/moltenbit)님께 감사드립니다.
#### 단계
1. psad를 설치합니다.
데비안 기반 시스템:
``` bash
sudo apt install psad
```
1. psad 구성 파일 `/etc/psad/psad.conf`를 백업합니다:
``` bash
sudo cp --archive /etc/psad/psad.conf /etc/psad/psad.conf-COPY-$(date +"%Y%m%d%H%M%S")
```
1. `/etc/psad/psad.conf`의 구성 옵션을 검토하고 업데이트합니다. 다음 항목에 특히 주의하세요:
|설정|설정값
|--|--|
|[`EMAIL_ADDRESSES`](http://www.cipherdyne.org/psad/docs/config.html#EMAIL_ADDRESSES)|귀하의 이메일 주소|
|`HOSTNAME`|서버의 호스트 이름|
|`EXPECT_TCP_OPTIONS`|`EXPECT_TCP_OPTIONS Y;`|
|`ENABLE_PSADWATCHD`|`ENABLE_PSADWATCHD Y;`|
|[`ENABLE_AUTO_IDS`](http://www.cipherdyne.org/psad/docs/config.html#ENABLE_AUTO_IDS)|`ENABLE_AUTO_IDS Y;`|
|`ENABLE_AUTO_IDS_EMAILS`|`ENABLE_AUTO_IDS_EMAILS Y;`|
자세한 내용은 http://www.cipherdyne.org/psad/docs/config.html에서 psad 문서의 구성 파일을 확인하세요.
1. <a name="psad_step4"></a>이제 PSAD가 트래픽을 분석할 수 있도록 UFW에 모든 트래픽을 로그하도록 지시하여 UFW가 PSAD와 함께 작동하도록 약간 수정해야 합니다. **두 개의 파일**을 편집하고 **COMMIT 줄 앞**에 다음 줄을 추가하면 됩니다.
백업:
``` bash
sudo cp --archive /etc/ufw/before.rules /etc/ufw/before.rules-COPY-$(date +"%Y%m%d%H%M%S")
sudo cp --archive /etc/ufw/before6.rules /etc/ufw/before6.rules-COPY-$(date +"%Y%m%d%H%M%S")
```
파일 편집:
- `/etc/ufw/before.rules`
- `/etc/ufw/before6.rules`
그리고 **COMMIT 줄 앞**에 다음을 추가합니다:
```
# log all traffic so psad can analyze
-A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
-A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
```
**참고**: 모든 iptables 로그에 로그 접두사를 추가하고 있습니다. 이는 [iptables 로그를 별도의 파일로 분리](#separate-iptables-log-file)할 때 필요합니다.
예:
> ```
> ...
>
> # log all traffic so psad can analyze
> -A INPUT -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
> -A FORWARD -j LOG --log-tcp-options --log-prefix "[IPTABLES] "
>
> # don't delete the 'COMMIT' line or these rules won't be processed
> COMMIT
> ```
1. 이제 변경 사항을 적용하기 위해 ufw와 psad를 다시 로드/재시작해야 합니다:
``` bash
sudo ufw reload
sudo psad -R
sudo psad --sig-update
sudo psad -H
```
1. iptables 규칙에서 오류를 분석합니다:
``` bash
sudo psad --fw-analyze
```
> ```
> [+] Parsing INPUT chain rules.
> [+] Parsing INPUT chain rules.
> [+] Firewall config looks good.
> [+] Completed check of firewall ruleset.
> [+] Results in /var/log/psad/fw_check
> [+] Exiting.
> ```
**참고**: 문제가 있으면 오류가 포함된 이메일을 받게 됩니다.
1. psad 상태 확인:
``` bash
sudo psad --Status
```
> ```
> [-] psad: pid file /var/run/psad/psadwatchd.pid does not exist for psadwatchd on vm
> [+] psad_fw_read (pid: 3444) %CPU: 0.0 %MEM: 2.2
> Running since: Sat Feb 16 01:03:09 2019
>
> [+] psad (pid: 3435) %CPU: 0.2 %MEM: 2.7
> Running since: Sat Feb 16 01:03:09 2019
> Command line arguments: [none specified]
> Alert email address(es): root@localhost
>
> [+] Version: psad v2.4.3
>
> [+] Top 50 signature matches:
> [NONE]
>
> [+] Top 25 attackers:
> [NONE]
>
> [+] Top 20 scanned ports:
> [NONE]
>
> [+] iptables log prefix counters:
> [NONE]
>
> Total protocol packet counters:
>
> [+] IP Status Detail:
> [NONE]
>
> Total scan sources: 0
> Total scan destinations: 0
>
> [+] These results are available in: /var/log/psad/status.out
> ```
([Table of Contents](#table-of-contents))
### 애플리케이션 침입 탐지 및 방지 (Fail2Ban 사용)
#### 이유
UFW는 서버에서 어떤 문을 봉쇄하여 아무도 볼 수 없게 하고, 어떤 문을 통해 인증된 사용자가 통과할 수 있도록 허용할지 알려줍니다. PSAD는 네트워크 활동을 모니터링하여 잠재적인 침입(반복된 접속 시도)을 탐지하고 방지합니다.
하지만 서버에서 실행 중인 SSH, Apache와 같은 애플리케이션/서비스는 어떨까요? 방화벽이 접근을 허용하도록 구성되어 있더라도, 모든 접근 시도가 유효하고 무해한 것은 아닙니다. 서버에서 실행 중인 웹 앱에 무차별 대입으로 침입하려는 시도가 있다면 어떻게 될까요? 여기서 Fail2ban이 필요합니다.
#### 작동 원리
Fail2ban은 애플리케이션(SSH, Apache 등)의 로그를 모니터링하여 잠재적인 침입을 탐지하고 방지합니다. 네트워크 트래픽/로그를 모니터링하고 의심스러운 활동(예: 짧은 시간 내에 여러 번의 연속 실패 연결)을 차단하여 침입을 방지합니다.
#### 목표
- 의심스러운 활동에 대한 네트워크 모니터링 및 위반 IP 자동 차단
#### 참고 사항
- 현재 이 서버에서 실행 중인 것은 SSH뿐이므로 Fail2ban이 SSH를 모니터링하고 필요에 따라 차단하도록 할 것입니다.
- 다른 프로그램을 설치할 때는 적절한 감옥(jail)을 생성/구성하고 활성화해야 합니다.
#### 참고 자료
- https://www.fail2ban.org/
- https://blog.vigilcode.com/2011/05/ufw-with-fail2ban-quick-secure-setup-part-ii/
- https://dodwell.us/security/ufw-fail2ban-portscan.html
- https://www.howtoforge.com/community/threads/fail2ban-and-ufw-on-debian.77261/
#### 단계
1. fail2ban을 설치합니다.
데비안 기반 시스템:
``` bash
sudo apt install fail2ban
```
1. `/etc/fail2ban/fail2ban.conf` 또는 `/etc/fail2ban/jail.conf`를 편집하지 않는 것이 좋습니다. 향후 업데이트에서 덮어쓸 수 있기 때문에 대신 로컬 복사본을 만듭니다. `/etc/fail2ban/jail.local` 파일을 만들고 `[LAN SEGMENT]`와 `[your email]`을 적절한 값으로 바꾼 후 다음 내용을 추가합니다:
```
[DEFAULT]
# the IP address range we want to ignore
ignoreip = 127.0.0.1/8 [LAN SEGMENT]
# who to send e-mail to
destemail = [your e-mail]
# who is the email from
sender = [your e-mail]
# since we're using exim4 to send emails
mta = mail
# get email alerts
action = %(action_mwl)s
```
**참고**: 서버가 이메일을 보낼 수 있어야 Fail2ban이 의심스러운 활동과 IP 차단 시 알림을 보낼 수 있습니다.
1. SSH에 대한 감옥을 생성해야 합니다. 이 감옥은 fail2ban이 SSH 로그를 보고 필요에 따라 ufw를 사용하여 IP를 차단/해제하도록 지시합니다. `/etc/fail2ban/jail.d/ssh.local` 파일을 만들고 다음 내용을 추가합니다:
```
[sshd]
enabled = true
banaction = ufw
port = ssh
filter = sshd
logpath = %(sshd_log)s
maxretry = 5
```
[게으른 분들을 위해](#editing-configuration-files---for-the-lazy):
``` bash
cat << EOF | sudo tee /etc/fail2ban/jail.d/ssh.local
[sshd]
enabled = true
banaction = ufw
port = ssh
filter = sshd
logpath = %(sshd_log)s
maxretry = 5
EOF
```
1. 위에서 fail2ban에 `banaction`으로 ufw를 사용하도록 지정했습니다. Fail2ban에는 ufw용 작업 구성 파일이 함께 제공됩니다. `/etc/fail2ban/action.d/ufw.conf`에서 확인할 수 있습니다.
1. fail2ban을 활성화합니다:
``` bash
sudo fail2ban-client start
sudo fail2ban-client reload
sudo fail2ban-client add sshd # sshd 감옥이 기본적으로 추가된 경우 일부 시스템에서 실패할 수 있습니다.
```
1. 상태 확인:
``` bash
sudo fail2ban-client status
```
> ```
> Status
> |- Number of jail: 1
> `- Jail list: sshd
> ```
``` bash
sudo fail2ban-client status sshd
```
> ```
> Status for the jail: sshd
> |- Filter
> | |- Currently failed: 0
> | |- Total failed: 0
> | `- File list: /var/log/auth.log
> `- Actions
> |- Currently banned: 0
> |- Total banned: 0
> `- Banned IP list:
> ```
#### 사용자 정의 감옥
아직 사용자 정의 감옥을 만들어야 할 필요는 없었습니다. 필요하게 되고 방법을 알게 되면 이 가이드를 업데이트하겠습니다. 또는 방법을 아신다면 [기여](#contributing)해 주시기 바랍니다.
#### IP 차단 해제
IP 차단을 해제하려면 다음 명령을 사용합니다:``` bash
fail2ban-client set [jail] unbanip [IP]
```
`[jail]`은 차단된 IP가 있는 감옥의 이름이고, `[IP]`는 차단 해제하려는 IP 주소입니다. 예를 들어, SSH에서 `192.168.1.100`을 차단 해제하려면 다음과 같이 합니다:``` bash
fail2ban-client set sshd unbanip 192.168.1.100
```
([Table of Contents](#table-of-contents))
### CrowdSec를 활용한 애플리케이션 침입 탐지 및 방지
#### 왜 필요한가
UFW는 서버에 어떤 문을 막아 아무도 볼 수 없게 하고, 어떤 문을 허가된 사용자가 통과할 수 있게 할지 알려줍니다. PSAD는 네트워크 활동을 모니터링하여 잠재적인 침입(반복적인 접속 시도)을 탐지하고 방지합니다.
CrowdSec는 Fail2Ban과 유사하게 애플리케이션(SSH, Apache 등)의 로그를 모니터링하여 잠재적인 침입을 탐지하고 방지합니다. 그러나 CrowdSec는 위협 인텔리전스를 CrowdSec에 공유하는 커뮤니티와 연동되어, 이후 모든 사용자에게 커뮤니티 차단 목록(Community Blocklist)을 배포합니다.
#### 작동 방식
CrowdSec는 애플리케이션(SSH, Apache 등)의 로그를 모니터링하여 잠재적인 침입을 탐지하고 방지합니다. 네트워크 트래픽/로그를 모니터링하고 의심스러운 활동(예: 짧은 시간 내에 여러 번의 연속적인 실패한 연결)을 차단하여 침입을 방지합니다. 악성 IP가 탐지되면 로컬 결정 목록에 추가되고, 위협 정보가 CrowdSec에 공유되어 커뮤니티 차단 목록이 업데이트됩니다. IP 주소가 일정 수준의 악성 활동 임계값에 도달하면, 다른 모든 CrowdSec 사용자에게 자동으로 전파되어 사전에 차단됩니다.
#### 목표
- 의심스러운 활동에 대한 네트워크 모니터링 및 문제 IP 자동 차단
#### 참고사항
- 현재 이 서버에서 실행 중인 것은 SSH뿐이므로, CrowdSec가 SSH를 모니터링하고 필요시 차단하도록 설정할 것입니다.
- 다른 프로그램을 설치할 때는 추가 컬렉션을 설치하고 적절한 수집 설정을 구성해야 합니다.
#### 참고 자료
- https://www.crowdsec.net/
- [CrowdSec가 커뮤니티 차단 목록을 관리하는 방법 읽기](https://www.crowdsec.net/our-data)
- [CrowdSec와 공유되는 위협 인텔리전스 읽기](https://docs.crowdsec.net/docs/next/central_api/intro#signal-meta-data)
- https://docs.crowdsec.net/
#### 단계
1. CrowdSec 보안 엔진(IDS) 설치
모든 Linux 배포판(Debian 계열 포함)에서
CrowdSec 저장소 설치:
``` bash
curl -s https://install.crowdsec.net | sudo sh
```
CrowdSec 보안 엔진 설치:
``` bash
sudo apt install crowdsec
```
> [!TIP]
> `curl | sh` 방식이 마음에 들지 않는다면, 다른 설치 방법은 [여기](https://docs.crowdsec.net/u/getting_started/installation/linux)에서 확인할 수 있습니다.
기본적으로 CrowdSec 보안 엔진을 설치하는 동안, 설치된 애플리케이션을 자동으로 검색하여 적절한 파서와 시나리오를 설치합니다. 대부분의 Linux 서버가 기본적으로 SSH를 실행하고 있으므로 CrowdSec가 자동으로 이를 구성합니다.
2. 복구 구성 요소(IPS) 설치
CrowdSec 자체는 탐지 엔진으로, 대부분의 최신 인프라에서는 업스트림 방화벽이나 WAF가 있을 수 있으므로 CrowdSec가 IP 주소를 직접 차단하지는 않습니다. 복구 구성 요소를 설치하여 CrowdSec가 탐지한 IP 주소를 차단할 수 있습니다.
```bash
sudo apt install crowdsec-firewall-bouncer-iptables
```
> [!TIP]
> UFW 설치가 `iptables`를 백엔드로 사용하지 않는 경우, 대신 `crowdsec-firewall-bouncer-nftables`를 설치할 수 있습니다. 설치된 바이너리는 동일하며, 설정 파일만 다릅니다.
기본적으로 복구 구성 요소를 설치하는 동안, 동일한 호스트에 배포된 경우(보안 엔진이 컨테이너 환경에 있지 않은 경우) 보안 엔진과 함께 작동하는 데 필요한 설정을 자동으로 구성합니다.
3. 탐지 및 복구가 의도한 대로 작동하는지 확인:
CrowdSec 패키지에는 보안 엔진 및 복구 구성 요소의 상태를 확인하는 CLI 도구가 포함되어 있습니다.
```bash
sudo cscli metrics
```
```bash
Acquisition Metrics:
╭────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────╮
│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │
├────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤
│ file:/var/log/auth.log │ 5 │ 4 │ 1 │ 10 │ - │
│ file:/var/log/syslog │ 30 │ - │ 30 │ - │ - │
╰────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯
Local API Decisions:
╭────────────────────────────────────────────┬────────┬────────┬───────╮
│ Reason │ Origin │ Action │ Count │
├────────────────────────────────────────────┼────────┼────────┼───────┤
│ crowdsecurity/http-backdoors-attempts │ CAPI │ ban │ 73 │
│ crowdsecurity/http-bad-user-agent │ CAPI │ ban │ 4836 │
│ crowdsecurity/http-path-traversal-probing │ CAPI │ ban │ 87 │
│ crowdsecurity/http-probing │ CAPI │ ban │ 2010 │
│ crowdsecurity/thinkphp-cve-2018-20062 │ CAPI │ ban │ 88 │
│ crowdsecurity/CVE-2019-18935 │ CAPI │ ban │ 7 │
│ crowdsecurity/CVE-2023-49103 │ CAPI │ ban │ 5 │
│ crowdsecurity/http-admin-interface-probing │ CAPI │ ban │ 91 │
│ ltsich/http-w00tw00t │ CAPI │ ban │ 3 │
│ crowdsecurity/apache_log4j2_cve-2021-44228 │ CAPI │ ban │ 18 │
│ crowdsecurity/nginx-req-limit-exceeded │ CAPI │ ban │ 280 │
│ crowdsecurity/ssh-slow-bf │ CAPI │ ban │ 3412 │
│ crowdsecurity/spring4shell_cve-2022-22965 │ CAPI │ ban │ 1 │
│ crowdsecurity/ssh-cve-2024-6387 │ CAPI │ ban │ 24 │
│ crowdsecurity/CVE-2023-22515 │ CAPI │ ban │ 2 │
│ crowdsecurity/http-cve-2021-41773 │ CAPI │ ban │ 172 │
│ crowdsecurity/netgear_rce │ CAPI │ ban │ 14 │
│ crowdsecurity/ssh-bf │ CAPI │ ban │ 2000 │
│ crowdsecurity/CVE-2022-35914 │ CAPI │ ban │ 1 │
│ crowdsecurity/http-cve-2021-42013 │ CAPI │ ban │ 2 │
│ crowdsecurity/jira_cve-2021-26086 │ CAPI │ ban │ 9 │
│ crowdsecurity/http-sensitive-files │ CAPI │ ban │ 166 │
│ crowdsecurity/http-wordpress-scan │ CAPI │ ban │ 272 │
│ crowdsecurity/CVE-2022-26134 │ CAPI │ ban │ 5 │
│ crowdsecurity/http-generic-bf │ CAPI │ ban │ 7 │
│ crowdsecurity/http-open-proxy │ CAPI │ ban │ 948 │
│ crowdsecurity/http-crawl-non_statics │ CAPI │ ban │ 339 │
│ crowdsecurity/http-cve-probing │ CAPI │ ban │ 5 │
│ crowdsecurity/CVE-2017-9841 │ CAPI │ ban │ 117 │
│ crowdsecurity/CVE-2022-37042 │ CAPI │ ban │ 1 │
│ crowdsecurity/fortinet-cve-2018-13379 │ CAPI │ ban │ 5 │
╰────────────────────────────────────────────┴────────┴────────┴───────╯
Local API Metrics:
╭──────────────────────┬────────┬──────╮
│ Route │ Method │ Hits │
├──────────────────────┼────────┼──────┤
│ /v1/alerts │ GET │ 2 │
│ /v1/decisions/stream │ GET │ 5 │
│ /v1/usage-metrics │ POST │ 2 │
│ /v1/watchers/login │ POST │ 4 │
╰──────────────────────┴────────┴──────╯
Local API Bouncers Metrics:
╭────────────────────────────────┬──────────────────────┬────────┬──────╮
│ Bouncer │ Route │ Method │ Hits │
├────────────────────────────────┼──────────────────────┼────────┼──────┤
│ cs-firewall-bouncer-1729025592 │ /v1/decisions/stream │ GET │ 5 │
╰────────────────────────────────┴──────────────────────┴────────┴──────╯
Local API Machines Metrics:
╭──────────────────────────────────────────────────┬────────────┬────────┬──────╮
│ Machine │ Route │ Method │ Hits │
├──────────────────────────────────────────────────┼────────────┼────────┼──────┤
│ <your_machine_id_will_be_here> │ /v1/alerts │ GET │ 2 │
╰──────────────────────────────────────────────────┴────────────┴────────┴──────╯
Parser Metrics:
╭─────────────────────────────────┬──────┬────────┬──────────╮
│ Parsers │ Hits │ Parsed │ Unparsed │
├─────────────────────────────────┼──────┼────────┼──────────┤
│ child-crowdsecurity/sshd-logs │ 41 │ 4 │ 37 │
│ child-crowdsecurity/syslog-logs │ 35 │ 35 │ - │
│ crowdsecurity/dateparse-enrich │ 4 │ 4 │ - │
│ crowdsecurity/sshd-logs │ 5 │ 4 │ 1 │
│ crowdsecurity/syslog-logs │ 35 │ 35 │ - │
╰─────────────────────────────────┴──────┴────────┴──────────╯
Scenario Metrics:
╭─────────────────────────────────────┬───────────────┬───────────┬──────────────┬────────┬─────────╮
│ Scenario │ Current Count │ Overflows │ Instantiated │ Poured │ Expired │
├─────────────────────────────────────┼───────────────┼───────────┼──────────────┼────────┼─────────┤
│ crowdsecurity/ssh-bf │ 1 │ - │ 1 │ 4 │ - │
│ crowdsecurity/ssh-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │
│ crowdsecurity/ssh-slow-bf │ 1 │ - │ 1 │ 4 │ - │
│ crowdsecurity/ssh-slow-bf_user-enum │ 1 │ - │ 1 │ 1 │ - │
╰─────────────────────────────────────┴───────────────┴───────────┴──────────────┴────────┴─────────╯
```
위 출력이 다소 복잡해 보일 수 있지만, 보안 엔진이 로그를 읽고 복구 구성 요소가 IP 주소를 차단하고 있는지 확인하는 좋은 방법입니다. 각 섹션에 대한 간략한 설명은 다음과 같습니다:
- **Acquisition Metrics**: 이 섹션은 보안 엔진이 읽고 구문 분석 중인 로그를 보여줍니다. `Lines unparsed` 열에 로그가 표시되면 보안 엔진이 로그를 구문 분석할 수 없음을 의미합니다. 이는 설정 오류 또는 로그가 예상 형식이 아닌 경우 발생할 수 있습니다.
- **Local API Decisions**: 이 섹션은 보안 엔진이 데이터베이스 내에 보유한 결정을 보여줍니다. `Count` 열에 로그가 표시되면 보안 엔진이 악성 활동을 탐지하고 IP 주소를 차단했음을 의미합니다.
- Orgin: 이는 결정이 발생한 출처입니다. 이 경우 중앙 API(CAPI)에서 가져온 것입니다.
- **Local API Metrics**: 이 섹션은 로컬 API에 대한 히트 수를 보여줍니다. 이 API는 보안 엔진이 복구 구성 요소와 통신하는 데 사용됩니다.
- **Local API Bouncers Metrics**: 이 섹션은 복구 구성 요소가 로컬 API에 대해 수행한 히트 수를 보여줍니다.
- **Local API Machines Metrics**: 이 섹션은 보안 엔진이 로컬 API에 대해 수행한 히트 수를 보여줍니다(중앙 집중식 설정에서 여러 보안 엔진을 실행하는 경우 여러 ID가 표시될 수 있음).
- **Parser Metrics**: 이 섹션은 보안 엔진이 사용 중인 파서를 보여줍니다. `Unparsed` 열에 로그가 표시되면 보안 엔진이 로그를 구문 분석할 수 없음을 의미합니다. 이는 설정 오류 또는 로그가 예상 형식이 아닌 경우 발생할 수 있습니다.
- **Scenario Metrics**: 이 섹션은 보안 엔진이 사용 중인 시나리오를 보여줍니다. `Current Count` 열에 로그가 표시되면 보안 엔진이 악성 활동을 탐지하고 해당 IP 주소를 추적 중임을 의미합니다.
#### IP 차단 해제
IP 차단을 해제하려면 다음 명령을 사용합니다:``` bash
cscli decisions delete --ip [IP]
```
`[IP]`는 차단 해제하려는 IP 주소입니다. 예를 들어, SSH에서 `192.168.1.100`을 차단 해제하려면 다음과 같이 합니다:``` bash
cscli decisions delete --ip 192.168.1.100
```
## 감사
### AIDE를 사용한 파일/폴더 무결성 모니터링 (WIP)
#### 이유
WIP
#### 작동 방식
WIP
#### 목표
WIP
#### 참고 자료
- https://aide.github.io/
- https://www.hiroom2.com/2017/06/09/debian-8-file-integrity-check-with-aide/
- https://blog.rapid7.com/2017/06/30/how-to-install-and-configure-aide-on-ubuntu-linux/
- https://www.stephenrlang.com/2016/03/using-aide-for-file-integrity-monitoring-fim-on-ubuntu/
- https://www.howtoforge.com/how-to-configure-the-aide-advanced-intrusion-detection-environment-file-integrity-scanner-for-your-website
- https://www.tecmint.com/check-integrity-of-file-and-directory-using-aide-in-linux/
- https://www.cyberciti.biz/faq/debian-ubuntu-linux-software-integrity-checking-with-aide/
- https://github.com/imthenachoman/How-To-Secure-A-Linux-Server/issues/83
#### 단계
1. AIDE를 설치합니다.
데비안 기반 시스템에서:
``` bash
sudo apt install aide aide-common
```
1. AIDE의 기본 파일을 백업합니다:
``` bash
sudo cp -p /etc/default/aide /etc/default/aide-COPY-$(date +"%Y%m%d%H%M%S")
```
1. `/etc/default/aide` 파일을 살펴보고 요구 사항에 따라 AIDE의 기본값을 설정합니다. 매일 실행하고 이메일을 받으려면 `CRON_DAILY_RUN`을 `yes`로 설정하세요.
1. AIDE 설정 파일을 백업합니다:
``` bash
sudo cp -pr /etc/aide /etc/aide-COPY-$(date +"%Y%m%d%H%M%S")
```
1. 데비안 기반 시스템에서:
- AIDE 설정 파일은 `/etc/aide/aide.conf.d/`에 있습니다.
- AIDE 문서와 설정 파일을 검토하여 요구 사항에 맞게 설정하세요.
- 새 설정(예: 새 폴더 모니터링)을 추가하려면 `/etc/aide/aide.conf` 또는 `/etc/aide/aide.conf.d/`에 추가하세요.
- 기본 설정 파일의 백업을 만드세요: `sudo cp -pr /etc/aide /etc/aide-COPY-$(date +"%Y%m%d%H%M%S")`.
1. 새 데이터베이스를 생성하고 설치합니다.
데비안 기반 시스템에서:
``` bash
sudo aideinit
```
> ```
> Running aide --init...
> Start timestamp: 2019-04-01 21:23:37 -0400 (AIDE 0.16)
> AIDE initialized database at /var/lib/aide/aide.db.new
> Verbose level: 6
>
> Number of entries: 25973
>
> ---------------------------------------------------
> The attributes of the (uncompressed) database(s):
> ---------------------------------------------------
>
> /var/lib/aide/aide.db.new
> RMD160 : moyQ1YskQQbidX+Lusv3g2wf1gQ=
> TIGER : 7WoOgCrXzSpDrlO6I3PyXPj1gRiaMSeo
> SHA256 : gVx8Fp7r3800WF2aeXl+/KHCzfGsNi7O
> g16VTPpIfYQ=
> SHA512 : GYfa0DJwWgMLl4Goo5VFVOhu4BphXCo3
> rZnk49PYztwu50XjaAvsVuTjJY5uIYrG
> tV+jt3ELvwFzGefq4ZBNMg==
> CRC32 : /cusZw==
> HAVAL : E/i5ceF3YTjwenBfyxHEsy9Kzu35VTf7
> CPGQSW4tl14=
> GOST : n5Ityzxey9/1jIs7LMc08SULF1sLBFUc
> aMv7Oby604A=
>
>
> End timestamp: 2019-04-01 21:24:45 -0400 (run time: 1m 8s)
> ```
1. 변경 사항 없이 모든 것이 제대로 작동하는지 테스트합니다.
데비안 기반 시스템에서:
``` bash
sudo aide.wrapper --check
```
> ```
> Start timestamp: 2019-04-01 21:24:45 -0400 (AIDE 0.16)
> AIDE found NO differences between database and filesystem. Looks okay!!
> Verbose level: 6
>
> Number of entries: 25973
>
> ---------------------------------------------------
> The attributes of the (uncompressed) database(s):
> ---------------------------------------------------
>
> /var/lib/aide/aide.db
> RMD160 : moyQ1YskQQbidX+Lusv3g2wf1gQ=
> TIGER : 7WoOgCrXzSpDrlO6I3PyXPj1gRiaMSeo
> SHA256 : gVx8Fp7r3800WF2aeXl+/KHCzfGsNi7O
> g16VTPpIfYQ=
> SHA512 : GYfa0DJwWgMLl4Goo5VFVOhu4BphXCo3
> rZnk49PYztwu50XjaAvsVuTjJY5uIYrG
> tV+jt3ELvwFzGefq4ZBNMg==
> CRC32 : /cusZw==
> HAVAL : E/i5ceF3YTjwenBfyxHEsy9Kzu35VTf7
> CPGQSW4tl14=
> GOST : n5Ityzxey9/1jIs7LMc08SULF1sLBFUc
> aMv7Oby604A=
>
>
> End timestamp: 2019-04-01 21:26:03 -0400 (run time: 1m 18s)
> ```
1. 일부 변경 후 모든 것이 제대로 작동하는지 테스트합니다.
데비안 기반 시스템에서:
``` bash
sudo touch /etc/test.sh
sudo touch /root/test.sh
sudo aide.wrapper --check
sudo rm /etc/test.sh
sudo rm /root/test.sh
sudo aideinit -y -f
```
> ```
> Start timestamp: 2019-04-01 21:37:37 -0400 (AIDE 0.16)
> AIDE found differences between database and filesystem!!
> Verbose level: 6
>
> Summary:
> Total number of entries: 25972
> Added entries: 2
> Removed entries: 0
> Changed entries: 1
>
> ---------------------------------------------------
> Added entries:
> ---------------------------------------------------
>
> f++++++++++++++++: /etc/test.sh
> f++++++++++++++++: /root/test.sh
>
> ---------------------------------------------------
> Changed entries:
> ---------------------------------------------------
>
> d =.... mc.. .. .: /root
>
> ---------------------------------------------------
> Detailed information about changes:
> ---------------------------------------------------
>
> Directory: /root
> Mtime : 2019-04-01 21:35:07 -0400 | 2019-04-01 21:37:36 -0400
> Ctime : 2019-04-01 21:35:07 -0400 | 2019-04-01 21:37:36 -0400
>
>
> ---------------------------------------------------
> The attributes of the (uncompressed) database(s):
> ---------------------------------------------------
>
> /var/lib/aide/aide.db
> RMD160 : qF9WmKaf2PptjKnhcr9z4ueCPTY=
> TIGER : zMo7MvvYJcq1hzvTQLPMW7ALeFiyEqv+
> SHA256 : LSLLVjjV6r8vlSxlbAbbEsPcQUB48SgP
> pdVqEn6ZNbQ=
> SHA512 : Qc4U7+ZAWCcitapGhJ1IrXCLGCf1IKZl
> 02KYL1gaZ0Fm4dc7xLqjiquWDMSEbwzW
> oz49NCquqGz5jpMIUy7UxA==
> CRC32 : z8ChEA==
> HAVAL : YapzS+/cdDwLj3kHJEq8fufLp3DPKZDg
> U12KCSkrO7Y=
> GOST : 74sLV4HkTig+GJhokvxZQm7CJD/NR0mG
> 6jV7zdt5AXQ=
>
>
> End timestamp: 2019-04-01 21:38:50 -0400 (run time: 1m 13s)
> ```
1. 이상입니다. `/etc/default/aide`에서 `CRON_DAILY_RUN`을 `yes`로 설정하면 cron이 매일 `/etc/cron.daily/aide`를 실행하고 결과를 이메일로 보내줍니다.
#### 데이터베이스 업데이트
AIDE가 모니터링하는 파일/폴더를 변경할 때마다 데이터베이스를 업데이트하여 변경 사항을 캡처해야 합니다. 데비안 기반 시스템에서 그렇게 하려면:``` bash
sudo aideinit -y -f
```
([Table of Contents](#table-of-contents))
### ClamAV를 사용한 안티바이러스 스캔 (WIP)
#### 이유
WIP
#### 작동 방식
- ClamAV는 바이러스 스캐너입니다.
- ClamAV-Freshclam은 바이러스 정의를 업데이트하는 서비스입니다.
- ClamAV-Daemon은 `clamd` 프로세스를 계속 실행하여 스캔 속도를 높입니다.
#### 목표
WIP
#### 참고 사항
- 이 지침은 `clamd`가 항상 실행되도록 ClamAV 데몬 서비스를 활성화하는 방법을 설명하지 **않습니다**. `clamd`는 메일 서버를 실행하는 경우에만 필요하며 파일의 실시간 모니터링을 제공하지 않습니다. 대신 수동으로 또는 일정에 따라 파일을 스캔해야 합니다.
#### 참고 자료
- https://www.clamav.net/documents/installation-on-debian-and-ubuntu-linux-distributions
- https://wiki.debian.org/ClamAV
- https://www.osradar.com/install-clamav-debian-9-ubuntu-18/
- https://www.lisenet.com/2014/automate-clamav-to-perform-daily-system-scan-and-send-email-notifications-on-linux/
- https://www.howtoforge.com/tutorial/configure-clamav-to-scan-and-notify-virus-and-malware/
- https://serverfault.com/questions/741299/is-there-a-way-to-keep-clamav-updated-on-debian-8
- https://askubuntu.com/questions/250290/how-do-i-scan-for-viruses-with-clamav
- https://ngothang.com/how-to-install-clamav-and-configure-daily-scanning-on-centos/
#### 단계
1. ClamAV 설치.
Debian 기반 시스템에서:
``` bash
sudo apt install clamav clamav-freshclam clamav-daemon
```
1. `clamav-freshclam`의 구성 파일 `/etc/clamav/freshclam.conf`를 백업하세요:
``` bash
sudo cp --archive /etc/clamav/freshclam.conf /etc/clamav/freshclam.conf-COPY-$(date +"%Y%m%d%H%M%S")
```
1. `clamav-freshclam`의 기본 설정은 대부분 충분하지만 변경하려면 파일 `/etc/clamav/freshclam.conf`를 편집하거나 `dpkg-reconfigure`를 사용할 수 있습니다:
``` bash
sudo dpkg-reconfigure clamav-freshclam
```
**참고**: 기본 설정은 하루에 24번 정의를 업데이트합니다. 간격을 변경하려면 `/etc/clamav/freshclam.conf`의 `Checks` 설정을 확인하거나 `dpkg-reconfigure`를 사용하세요.
1. `clamav-freshclam` 서비스를 시작하세요:
``` bash
sudo service clamav-freshclam start
```
1. `clamav-freshclam`이 실행 중인지 확인할 수 있습니다:
``` bash
sudo service clamav-freshclam status
```
> ```
> ● clamav-freshclam.service - ClamAV virus database updater
> Loaded: loaded (/lib/systemd/system/clamav-freshclam.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-03-16 22:57:07 EDT; 2min 13s ago
> Docs: man:freshclam(1)
> man:freshclam.conf(5)
> https://www.clamav.net/documents
> Main PID: 1288 (freshclam)
> CGroup: /system.slice/clamav-freshclam.service
> └─1288 /usr/bin/freshclam -d --foreground=true
>
> Mar 16 22:57:08 host freshclam[1288]: Sat Mar 16 22:57:08 2019 -> ^Local version: 0.100.2 Recommended version: 0.101.1
> Mar 16 22:57:08 host freshclam[1288]: Sat Mar 16 22:57:08 2019 -> DON'T PANIC! Read https://www.clamav.net/documents/upgrading-clamav
> Mar 16 22:57:15 host freshclam[1288]: Sat Mar 16 22:57:15 2019 -> Downloading main.cvd [100%]
> Mar 16 22:57:38 host freshclam[1288]: Sat Mar 16 22:57:38 2019 -> main.cvd updated (version: 58, sigs: 4566249, f-level: 60, builder: sigmgr)
> Mar 16 22:57:40 host freshclam[1288]: Sat Mar 16 22:57:40 2019 -> Downloading daily.cvd [100%]
> Mar 16 22:58:13 host freshclam[1288]: Sat Mar 16 22:58:13 2019 -> daily.cvd updated (version: 25390, sigs: 1520006, f-level: 63, builder: raynman)
| 설정 | 유효한 값 | 예제 | 설명 | 참고 |
|---|
| AllowGroups | 로컬 UNIX 그룹 이름 | AllowGroups sshusers | SSH 접속을 허용할 그룹 | |
| ClientAliveCountMax | 숫자 | ClientAliveCountMax 3 | 응답 없이 전송되는 최대 클라이언트 활성 메시지 수 | |
| ClientAliveInterval | 초 단위 | ClientAliveInterval 15 | 응답 요청 전 제한 시간(초) | |
| ListenAddress | 공백으로 구분된 로컬 주소 목록 |
| sshd가 수신해야 하는 로컬 주소 | 중요한 세부 사항은 Issue #1을 참조하세요. |
| LoginGraceTime | 초 단위 | LoginGraceTime 30 | 로그인이 시간 초과되기까지의 시간(초) | |
| MaxAuthTries | 숫자 | MaxAuthTries 2 | 허용되는 최대 로그인 시도 횟수 | |
| MaxSessions | 숫자 | MaxSessions 2 | 최대 열린 세션 수 | |
| MaxStartups | 숫자 | MaxStartups 2 | 최대 로그인 세션 수 | |
| PasswordAuthentication | yes 또는 no | PasswordAuthentication no | 비밀번호 로그인 허용 여부 | |
| Port | 열려 있는 사용 가능한 포트 번호 | Port 22 | sshd가 수신해야 하는 포트 |
이 설정의 의미에 대한 자세한 내용은 man sshd_config를 확인하세요.