PHP2Shell 막기 위해 php 업그레이드 하기

0단계: 지금 어느 서버에서, 어떤 상태인지 확인

hostname
php -v | head -1
systemctl is-active php8.3-fpm php8.5-fpm
sudo ss -tlnp | grep 9000
  • hostname: 작업할 서버가 맞는지 확인합니다. 오늘 두 서버를 오가면서 헷갈린 적이 있으니 매번 확인하세요.
  • systemctl is-active: 첫 줄이 8.3, 둘째 줄이 8.5의 상태입니다(active 또는 inactive).
  • ss ... 9000: 지금 9000번 포트로 PHP 요청을 받는 프로그램입니다. nginx는 이 포트로 PHP를 넘깁니다. 여기에 php-fpm8.3이 보이는 게 전환 전의 정상 상태입니다.

1단계: 8.3 설정 백업

bash

sudo cp -a /etc/php/8.3 ~/php83-etc-backup

8.3에서 쓰던 설정 전체를 홈 폴더에 복사해 둡니다. 나중에 8.3을 지우거나 문제가 생겼을 때 참고용입니다. 출력은 없습니다.


2단계: PHP 8.5 설치

sudo apt install php8.5-fpm php8.5-cli php8.5-common php8.5-mysql php8.5-curl \
  php8.5-gd php8.5-imagick php8.5-intl php8.5-mbstring php8.5-readline \
  php8.5-xml php8.5-zip php8.5-bz2 php8.5-redis php8.5-igbinary
  • 8.3에서 쓰던 모듈들의 8.5 버전을 설치합니다.
  • php8.5-opcache는 필요 없습니다. 8.5부터는 PHP에 기본으로 포함돼 있습니다.
  • 설치하는 동안 8.3은 계속 돌고 있으니 사이트는 영향을 받지 않습니다.

⚠️ 이미 3단계(풀 설정 복사)를 해둔 상태에서 설치하면 마지막에 error processing package php8.5-fpm이 날 수 있습니다. 8.5가 9000번 포트를 쓰려는데 8.3이 이미 쓰고 있어서 생기는 일이고, 정상입니다. 7단계에서 해결됩니다.


3단계: FPM 풀 설정 옮기기

풀 설정은 PHP가 어디서 요청을 받을지(9000번 포트)와 프로세스를 몇 개 띄울지를 정하는 파일입니다.

sudo cp /etc/php/8.5/fpm/pool.d/www.conf ~/www.conf.85-default
sudo cp /etc/php/8.3/fpm/pool.d/*.conf /etc/php/8.5/fpm/pool.d/
grep -n "^listen" /etc/php/8.3/fpm/pool.d/*.conf /etc/php/8.5/fpm/pool.d/*.conf
  1. 첫 줄은 8.5 기본 설정을 백업합니다.
  2. 둘째 줄은 8.3의 풀 설정을 8.5로 복사합니다.
  3. 셋째 줄로 비교합니다. 8.3과 8.5 모두 listen = 127.0.0.1:9000이면 됩니다.

4단계: php.ini 값 옮기기

php.ini는 업로드 용량, 메모리 한도처럼 PHP가 어떻게 동작할지를 정합니다. 8.5는 새로 설치돼서 모두 기본값이므로, 그대로 두면 2MB 넘는 이미지를 올릴 수 없게 됩니다.

4-1. 비교

grep -E "^(memory_limit|upload_max_filesize|post_max_size|max_execution_time|max_input_time|date.timezone)" \
  /etc/php/8.3/fpm/php.ini /etc/php/8.5/fpm/php.ini

같은 항목끼리 8.3과 8.5의 값을 비교합니다.

4-2. 8.3 값으로 맞추기 (아래는 doru1-vm의 값입니다. 4-1에서 본 이 서버의 8.3 값으로 바꿔서 실행하세요)

aphps02
sudo cp /etc/php/8.5/fpm/php.ini ~/php.ini.85-default
sudo sed -i \
  -e 's/^max_execution_time = .*/max_execution_time = 3600/' \
  -e 's/^max_input_time = .*/max_input_time = 3600/' \
  -e 's/^memory_limit = .*/memory_limit = 256M/' \
  -e 's/^post_max_size = .*/post_max_size = 100M/' \
  -e 's/^upload_max_filesize = .*/upload_max_filesize = 100M/' \
  -e 's#^;date.timezone =.*#date.timezone = Asia/Seoul#' \
  /etc/php/8.5/fpm/php.ini

4-3. 다시 비교
4-1 명령을 한 번 더 실행해서 8.3과 8.5의 값이 똑같이 나오는지 확인합니다.


5단계: 빠진 모듈이 없는지 확인

diff <(ls /etc/php/8.3/fpm/conf.d/ | sed 's/^[0-9]*-//') <(ls /etc/php/8.5/fpm/conf.d/ | sed 's/^[0-9]*-//')
  • <로 시작하는 줄은 8.3에만 있는 모듈입니다. opcache.ini는 무시하고, 그 밖의 것이 있으면 sudo apt install php8.5-이름으로 설치합니다.
  • >로 시작하는 줄은 8.5에만 있는 모듈이라 그냥 둬도 됩니다.

6단계: 설정 검사

sudo php-fpm8.5 -t

마지막 줄에 test is successful이 나와야 합니다. ERROR가 나오면 여기서 멈추고 메시지를 보여주세요.


7단계: 전환 (사이트가 몇 초 끊김)

bas

sudo systemctl disable --now php8.3-fpm
sudo dpkg --configure -a
sudo systemctl enable php8.5-fpm
sudo systemctl restart php8.5-fpm
  1. 8.3 끄기: 9000번 포트를 비웁니다. 재부팅해도 다시 켜지지 않게 합니다.
  2. dpkg --configure -a: 2단계에서 에러가 났다면 그때 멈춘 설치를 마무리합니다. 에러가 없었다면 아무 일도 하지 않습니다.
  3. 8.5 자동 시작 설정: 재부팅 후에도 8.5가 켜지게 합니다.
  4. 8.5 재시작: 오늘 python-server에서 문제가 됐던 부분입니다. 8.5는 설치될 때 기본 설정으로 이미 켜져 있을 수 있어서, 재시작을 해야 3~4단계에서 바꾼 설정이 적용됩니다. enable --now는 이미 켜져 있는 서비스를 다시 시작하지 않으니, 반드시 restart를 해주세요.

8단계: 확인

8-1. 9000번 포트 확인 (가장 중요)

sudo ss -tlnp | grep 9000

php-fpm8.5가 보여야 합니다. 비어 있으면 사이트가 내려간 상태이니 바로 9단계(되돌리기)를 하세요.

8-2. 사이트 응답 확인

sudo nginx -T 2>/dev/null | grep -E "^\s*server_name" | sort -u
curl -sI https://<도메인> | head -1

첫 줄은 이 서버의 도메인 목록입니다. 도메인마다 200이나 301/302가 나오면 정상이고, 502나 500이 나오면 문제가 있는 겁니다.

8-3. 터미널 PHP 확인

sudo update-alternatives --set php /usr/bin/php8.5
php -v | head -1

8-4. 에러 로그 확인

sudo tail -n 20 /var/log/php8.5-fpm.log
sudo tail -n 20 /var/log/nginx/error.log

8-5. 브라우저 확인
사이트 메인 화면, 관리자 화면, 글쓰기, 이미지 업로드를 한 번씩 해보세요.


9단계: 문제가 생기면 되돌리기

sudo systemctl disable --now php8.5-fpm
sudo systemctl enable --now php8.3-fpm
sudo update-alternatives --set php /usr/bin/php8.3
sudo ss -tlnp | grep 9000

9000번 포트에 php-fpm8.3이 다시 보이면 원래대로 돌아온 겁니다.


10단계: 며칠 뒤 8.3 정리

8.5에서 며칠 문제없이 돌아가면 8.3을 지웁니다.

aphps01
sudo apt purge 'php8.3-*'
sudo apt purge $(dpkg -l | awk '/^rc/ && $2 ~ /^php/ {print $2}')
sudo apt autoremove
  이 사이트는 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

Leave a Comment