# 9. 보안 관리 [목차로 돌아가기](./README.md) --- ## SSH 키 관리 양쪽 서버 모두 비밀번호 로그인 비활성화, root SSH 비활성화, 키 인증만 허용. ```bash # SSH 설정 확인 sudo grep -E "^(PasswordAuthentication|PermitRootLogin|PubkeyAuthentication)" /etc/ssh/sshd_config # 올바른 설정: # PasswordAuthentication no # PermitRootLogin no # PubkeyAuthentication yes ``` ### [운영] 공개키 관리 ```bash cat /home/hskwon/.ssh/authorized_keys # 새 공개키 추가 echo "새_공개키_내용" >> /home/hskwon/.ssh/authorized_keys # SSH 설정 변경 후 반드시 재시작 sudo systemctl restart sshd ``` ### [CI/CD] 공개키 관리 ```bash cat /home/hskwon/.ssh/authorized_keys echo "ssh-ed25519 AAAA... user@host" >> /home/hskwon/.ssh/authorized_keys chmod 600 /home/hskwon/.ssh/authorized_keys ``` ### [CI/CD] Jenkins SSH 키 ```bash # 경로: /var/lib/jenkins/.ssh/id_ed25519 # 공개키는 운영서버/개발서버 hskwon authorized_keys에 등록됨 sudo cat /var/lib/jenkins/.ssh/id_ed25519.pub # 연결 테스트 sudo -u jenkins ssh -i /var/lib/jenkins/.ssh/id_ed25519 hskwon@211.117.60.189 "hostname && date" sudo -u jenkins ssh -i /var/lib/jenkins/.ssh/id_ed25519 hskwon@114.203.209.83 "hostname && date" # known_hosts 갱신 (호스트 키 변경 시) sudo -u jenkins ssh-keygen -R 211.117.60.189 sudo -u jenkins ssh-keyscan -H 211.117.60.189 >> /var/lib/jenkins/.ssh/known_hosts ``` --- ## UFW (방화벽) 관리 ### [운영] 규칙 | 포트 | 허용 범위 | 용도 | |------|-----------|------| | 22 | Anywhere | SSH | | 80 | Anywhere | HTTP | | 443 | Anywhere | HTTPS | | 9100 | 110.10.147.46 only | node_exporter | | 3306 | 110.10.147.46 only | MySQL 백업 | ### [CI/CD] 규칙 | 포트 | 허용 범위 | 용도 | |------|-----------|------| | 22 | Anywhere | SSH | | 80 | Anywhere | HTTP | | 443 | Anywhere | HTTPS | ### [개발] 규칙 | 포트 | 허용 범위 | 용도 | |------|-----------|------| | 22 | Anywhere | SSH | | 80 | Anywhere | HTTP | | 443 | Anywhere | HTTPS | | 3000 | Anywhere | Gitea | > MySQL(3306), Apache(8080), Next.js(3001) 등은 외부 차단됨 ### 공통 명령어 ```bash # 규칙 확인 sudo ufw status numbered # 규칙 추가 sudo ufw allow from IP주소 to any port 포트번호 # 규칙 삭제 sudo ufw delete 규칙_번호 # 변경사항은 즉시 적용 (재시작 불필요) ``` **주의:** SSH (22/tcp) 규칙 삭제 금지 ```bash # 변경 전 백업 (CI/CD) sudo ufw status numbered > /tmp/ufw-backup-$(date +%Y%m%d).txt ``` --- ## SSL 인증서 관리 ```bash # 인증서 만료일 전체 확인 sudo certbot certificates # 자동 갱신 타이머 확인 sudo systemctl status certbot.timer # 새 도메인 인증서 발급 sudo certbot --nginx -d 새도메인 --email develop@codebridge-x.com # 수동 갱신 sudo certbot renew # 인증서 삭제 sudo certbot delete --cert-name 도메인명 ``` --- ## fail2ban 관리 ```bash # jail 상태 확인 sudo fail2ban-client status sudo fail2ban-client status sshd # IP 차단 해제 sudo fail2ban-client set sshd unbanip IP주소 # jail 재시작 sudo fail2ban-client restart sshd ``` ### 화이트리스트 설정 **현재 설정:** | 서버 | ignoreip | |------|----------| | 운영 | 127.0.0.1/8, 110.10.147.46 (CI/CD) | | CI/CD | 127.0.0.1/8, 211.117.60.189 (운영) | | 개발 | 127.0.0.1/8, 110.10.147.46 (CI/CD), 211.117.60.189 (운영) | ```bash # /etc/fail2ban/jail.local [DEFAULT] ignoreip = 127.0.0.1/8 110.10.147.46 211.117.60.189 # 변경 후 sudo systemctl restart fail2ban ``` --- ## [운영] .env 파일 보안 > **주의:** `.env` 권한은 반드시 `640` (`-rw-r-----`)이어야 합니다. > PHP-FPM은 `www-data` 사용자(webservice 그룹)로 실행되므로 그룹 읽기 권한이 필요합니다. > `600`으로 설정하면 PHP-FPM이 .env를 읽지 못해 **전체 서비스 500 에러**가 발생합니다. > (실제 장애 사례: 2026-03-03, 08-troubleshooting.md 참조) ```bash # 권한 확인 (640이어야 함 — 소유자 rw + 그룹 r) ls -la /home/webservice/api/shared/.env ls -la /home/webservice/mng/shared/.env ls -la /home/webservice/sales/.env # 권한 수정 chmod 640 /home/webservice/api/shared/.env chmod 640 /home/webservice/mng/shared/.env chmod 640 /home/webservice/sales/.env ``` ### vi 편집 시 권한 변경 방지 `vi`로 파일을 편집하면 새 파일로 교체되면서 권한이 `600`으로 초기화될 수 있습니다. 이를 방지하기 위해 서버 계정의 `~/.vimrc`에 아래 설정을 추가합니다: ```bash # 원본 파일에 직접 덮어쓰기 (권한 유지) echo "set backupcopy=yes" >> ~/.vimrc ``` **적용 현황 (2026-03-03):** - sam-prod: hskwon, pro 계정 적용 완료 - sam-cicd: hskwon, pro 계정 적용 완료 --- ## [운영] Redis 보안 Redis는 127.0.0.1에만 바인딩되어 외부 접근 불가. ```bash redis-cli config get bind # "127.0.0.1 ::1" grep "^bind" /etc/redis/redis.conf ``` --- ## [운영] MySQL 사용자 관리 ```bash # 사용자 목록 sudo mysql -e "SELECT user, host, plugin FROM mysql.user;" # 비밀번호 변경 sudo mysql -e "ALTER USER 'codebridge'@'localhost' IDENTIFIED BY '새_비밀번호'; FLUSH PRIVILEGES;" # 외부 접근 사용자 확인 sudo mysql -e "SELECT user, host FROM mysql.user WHERE host != 'localhost';" ``` --- ## [CI/CD] Jenkins 보안 - Jenkins Credentials에서만 민감 정보 관리 - Jenkinsfile에 직접 비밀번호 기재 금지 - 관리자: hskwon - 사용자 추가: Jenkins 관리 > Users > Create User --- ## [CI/CD] Gitea 접근 제어 - 회원가입 비활성화 (DISABLE_REGISTRATION = true) - 로그인 필수 (REQUIRE_SIGNIN_VIEW = true) - API 토큰 기반 인증 - 사용자 추가: CLI 또는 관리자 웹 UI