오래된 우회 방법이 OpenVPN 실행 파일을 다른 곳으로 옮기고 원래 경로에는 셸 래퍼를 남겨 두었습니다. 몇 달 뒤 업그레이드가 들어오면 그 우회 방법을 되돌리는 일은 어느 파일이 진짜 클라이언트인지 맞히는 게임이 됩니다. 명령 이름, 서비스에 설정된 실행 파일, 패키지 자체의 파일 목록은 모두 서로 다른 대상을 가리킬 수 있고, 하나만 고치고 나머지를 두면 고쳐진 것처럼 보이면서 더 나쁘게 동작하는 호스트가 만들어집니다.

서비스가 실행하는 경로부터 시작하세요

터미널과 systemd 유닛은 실행 파일을 같은 방식으로 해석하지 않습니다. 셸은 PATH를 뒤지고 유닛은 경로를 지정하며, 게다가 drop-in 덮어쓰기는 지금 읽고 있는 파일을 건드리지 않고 그 경로를 바꿀 수 있습니다. 이 차이가 이 작업의 혼란 대부분을 설명합니다. 어떤 파일을 고쳐야 하는지도 이 차이가 결정합니다.

유닛에게 무엇을 실행하는지 물어보고, 그것을 바꾸는 drop-in까지 포함해 확인한 뒤, 권위 있다고 가정한 조각이 아니라 결과로 나오는 ExecStart 줄을 읽으세요. 그다음 그 경로를 어떤 심볼릭 링크를 거치든 최종 파일까지 따라가세요. 숨은 디렉터리로 exec 하며 끝나는 래퍼는 이런 옛 수정에서 흔한 구성입니다.

무엇이든 바꾸기 전에 해석된 경로를 적어 두세요.

systemctl cat [email protected] | grep -n 'ExecStart'
readlink -f "$(command -v openvpn)"

명령 이름과 서비스 경로를 비교하세요

두 답은 자주 다르며, 그 차이가 곧바로 결함은 아닙니다. NetworkManager 플러그인이 자체 경로를 실행할 수 있고, 컨테이너가 또 다른 경로를 마운트할 수 있습니다.

중요한 것은 트래픽을 처리하는 프로세스를 어느 소유자가 실행하는지 아는 것입니다. 유닛이 /usr/local/sbin/openvpn-wrapper 을 실행하는데 셸이 /usr/sbin/openvpn 을 해석한다면, 두 번째 파일을 고쳐도 서비스에는 아무 변화가 없습니다.

각 후보를 어느 패키지가 소유하는지 물어보고, 그 파일이 패키지 관리 대상인지 로컬에 놓인 것인지 판단하세요. 소유 패키지가 없는 파일은 누군가 의도적으로 그곳에 둔 파일이며, 지우기 전에 이름과 소유자와 이유를 갖출 가치가 있습니다. 반대 실수도 흔한데, 포럼 글이 같은 디렉터리를 썼다는 이유로 예전에 저장한 바이너리로 패키지 파일을 덮어쓰는 일입니다.

패키지 파일에 대해서는 패키지 데이터베이스가 말하게 하세요

소프트웨어가 Debian 패키지에서 왔다면, 패키지 데이터베이스는 그 파일들이 설치된 내용과 아직 일치하는지 알려 줄 수 있습니다. 이것은 무결성에 관한 좁은 질문이지 보안 판정이 아니며, 무엇을 고칠지 결정할 때 그 차이가 중요합니다. 불일치는 설치 후 파일이 바뀌었다는 뜻이고, 그것이 예전 우회 방법일 수도 정당한 로컬 편집일 수도 있습니다. 출력은 어느 쪽인지 결정하지 않으므로 결론이 아니라 단서로 읽으세요.

검증을 실행하고, 빈 결과를 무언가의 증거로 삼는 대신 출력을 읽으세요.

dpkg -S /usr/sbin/openvpn
dpkg --verify openvpn

dpkg 설명서 에 따르면 검증은 설치된 파일을 로컬에 기록된 메타데이터와 비교하며, 있는 경우 저장된 체크섬을 사용합니다. 바뀐 패키지 파일은 알아채지만, 그 대신 다른 바이너리가 실행되는지까지는 알려 주지 못합니다.

고치기 전에 상태를 기록하세요

해석된 실행 경로, 파일의 패키지 관계, 래퍼의 위치, 그리고 그것을 도입한 변경 기록을 모으세요. 나중에 필요할 통합 작업이 래퍼에 들어 있다면 보호된 곳에 복사하세요.

이런 스크립트는 때때로 자격 증명이나 게이트웨이 세부 정보를 담고 있으므로, 읽기 전에 래퍼 내용을 지원 스레드에 붙여 넣지 마세요.

터널을 다시 시작하면 호스트를 관리하는 세션이 끊길 수 있으므로, 작업하는 동안 서비스가 어떤 프로필을 쓰는지, 누가 접속해 있는지 기록하세요.

실행을 검증한 다음 래퍼를 정리하세요

수정 후 서비스를 시작하고 프로세스가 의도한 경로로 실행되는지 확인하세요. 손으로 실행한 버전 질의는 파일이 동작함을 증명하지만, 유닛이 그것을 쓴다는 것까지 증명하지는 않습니다.

원래 옵션을 무시하는 바이너리 교체는 인증서 문제처럼 보이는 방식으로 실패하므로, 그다음 클라이언트를 다시 연결해 프로필이 여전히 인증되는지 확인하세요.

밀려난 래퍼는 그것을 도입한 같은 변경 기록을 통해 정리하세요. 끝난 수정은 어떤 실행 파일이 돌고, 왜 그런지, 어떤 파일을 제거했는지를 밝히며, 파일 이름을 되돌리고 바라는 것과는 다릅니다.

관련 글