호스트 간 마이그레이션 시 사용자 세션 유지

안녕하세요!

몇 가지 Discourse 인스턴스를 새로운 호스팅으로 이전하는 작업을 준비 중입니다. 계획은 기존 사이트를 읽기 전용으로 설정한 뒤 백업을 받아, 이를 새 호스팅으로 옮긴 후 복원하면서 DNS 설정(짧은 TTL)을 업데이트하는 것입니다. 이 과정은 이곳과 다른 곳의 가이드에서 참고한 것입니다.

DNS 업데이트를 시뮬레이션하기 위해 /etc/hosts 파일 해킹을 사용하고(브라우저에서도 DNS over HTTPS를 비활성화한 상태) 몇 차례 사전 테스트를 해봤습니다. 지금까지는 문제가 없습니다.

하지만 ‘소스’ 사이트에서 브라우저를 닫은 뒤, ‘대상’ 사이트에서 이전이 완전히 끝난 후에만 브라우저를 열도록 주의했음에도 불구하고, 로그인 상태가 기억되지 않습니다.

물론 이전 작업으로 인해 사이트 멤버들이 모두 로그아웃되는 것은 원치 않습니다. 어디를 확인해야 하거나, 제가 놓치고 있는 부분이 있을까요?

현재 테스트 중인 사용자는 관리자 권한을 가지고 있으며 2FA를 사용 중입니다. 또한 Discourse 컨테이너는 SSL을 종료하는 Nginx 뒤에 위치해 있는데, 이것이 문제 해결에 영향을 미칠까요?

도움 주시면 감사하겠습니다!

저도 같은 문제를 겪고 있어서 해결하고 싶습니다.

조언 주시면 감사하겠습니다.

2FA와 관련이 있을 수 있으니, 2FA 없이 테스트 계정을 몇 개 만들어서 시도해볼 생각입니다. 사이트 회원 중 2FA를 사용하는 사람이 매우 적으므로, 단순히 해당 세션만 유실되는 것이라면 허용할 수 있을 것 같습니다.

또한 소스 서버와 대상 서버가 NTP에 동기화되어 있는지 확인할 예정입니다. 지금은 두 서버 간 시차가 몇 초를 넘지 않을 것 같지만요.

그 외에는, 인증 토큰에 어떤 정보가 포함되는지, 그리고 어떤 부분이 문제를 일으키고 있는지 파악하기 위해 소스 코드를 살펴보는 수밖에 없을 것 같습니다… :grimacing:

최선의 방법은 사용자에게 변경 사항을 알리고, 로그아웃 처리되며 다시 로그인해야 한다는 점을 설명하는 것입니다.

각 서버에는 SSL이 적용되어 고유한 서명이 있습니다.

서버 설정을 변경하는 것보다 사용자에게 다시 로그인하도록 하는 것이 훨씬 수월합니다.

불편을 드린 것에 대해 사과하되, 이것이 더 나은 방향임을 강조하세요.

정말 그런가요?

세션 쿠키는 SSL "서명"에 어떻게 영향을 받나요? (특히 제 경우처럼, 새 호스트와 기존 호스트가 동일한 도메인 이름에서 동일한 SSL 인증서 파일을 사용하는 경우)

회원분들에게 사과하는 것에는 (:slightly_smiling_face:) 전혀 문제가 없지만, 다음과 같은 몇 가지 불리한 부작용을 예상할 수 있어 그런 상황을 정말로 피하고 싶습니다:

  1. 회원들이 다시 로그인하지 않고, 향후 포럼에 참여할 가능성이 낮아집니다.
  2. 회원들이 비밀번호를 잊고 비밀번호 복구 도움이 필요합니다.
  3. 회원들이 비밀번호를 잊고 새 계정을 생성하여, 포럼에 수많은 '좀비 계정’이 남고 사용자 메모나 게시글 이력 등이 없는 중복된 신원들이 혼란을 야기합니다.

SSL 부분은 Discourse 앞단에서 모두 정상적으로 작동합니다(호스트 파일 해킹을 사용하더라도). 생각해 보면, 그렇지 않으면 로드 밸런서에 문제가 생길 것이므로 그럴 수밖에 없습니다. 제 아는데로, 이 설정에서는 SSL이 Nginx에서 종료되므로 Discourse는 SSL에 대해 알지조차 못합니다.

다른 질문은 '모든 사용자를 로그아웃하지 않고 Discourse 서버를 새 IP로 이전할 수 있는가’입니다. 가능하다고 생각했는데, 아마 그 가정은 틀렸을 수도 있습니다… :frowning:

백업 및 복원 후에도 포럼 세션이 유지되는 경우가 분명히 있었어요. 여기에서 무슨 일이 일어나고 있는지 정말로 모르겠어요 :frowning:

세션 쿠키는 무작위로 생성된 시크릿 키를 사용하여 암호화되며, 기본적으로 이 키는 redis에 저장됩니다. Redis 데이터는 백업에 포함되지 않으므로 사이트를 새 서버로 복원할 때 새로운 시크릿 키가 재생성됩니다.

app.yml 파일의 환경 변수 DISCOURSE_SECRET_KEY_BASE를 사용하여 시크릿 키를 수동으로 설정할 수 있습니다. 세션을 유지하려면 다음과 같은 방법을 시도해 볼 수 있습니다:

  1. 기존 서버에서 콘솔에 접속하여 redis에서 시크릿 키를 확인합니다.

    pry(main)> GlobalSetting.safe_secret_key_base
    => "5fb9dc98be368599e0a..."
    
  2. (1)에서 찾은 값을 사용하여 기존 서버의 app.yml 파일 env: 섹션에 DISCOURSE_SECRET_KEY_BASE를 추가하고 앱을 다시 빌드합니다. 이론적으로 모든 것이 올바르게 진행되면 Discourse는 이제 app.yml의 값을 사용하게 되고 사용자 세션이 유지됩니다. 다음을 실행하여 환경 변수가 사용되고 있는지 확인할 수 있습니다.

    GlobalSetting.secret_key_base
    
  3. 새 서버의 app.yml 파일에도 동일한 SECRET_KEY_BASE가 있는지 확인합니다. 백업을 복원하면 사용자 세션이 유지되어야 합니다.

이 플로우를 테스트해 보지 않았으므로, 프로덕션 포럼에 사용할 계획이라면 먼저 반드시 테스트해 보시기 바랍니다!

참고: 여러 Discourse 인스턴스 간에 시크릿 키를 공유해서는 안 됩니다. 시크릿 키를 보유하면 누군가가 사이트에서 자신의 세션 쿠키를 복호화하고 수정할 수 있으며, 이는 매우 심각한 보안 문제를 초래할 수 있습니다.

훌륭합니다 - 샌드박스 인스턴스에서 이걸 직접 시도해 볼게요. 작동하는지 확인해서 다시 보고드리겠습니다 :slight_smile:

이해했습니다. 이제 백업에서 이 키를 내보낼 수 있는 옵션에 대한 기능 요청을 해야 하는지 고민 중입니다. 제게는 수천 개의 계정이 있는 사이트에서 모든 세션을 잃는 것은 '매우 나쁜 일’로 여겨집니다. 마이그레이션을 연습하면서 이 문제가 드러났지만, 만약 기계나 Docker 인스턴스가 어떤 이유로든 손실되면 키도 함께 손실되어 동일한 세션 손실을 겪게 될 것입니다.

마이그레이션 관련 주제에서 이 '기능’에 대해 언급하는 것도 좋을 것 같습니다: Move your Discourse Instance to a Different Server

보안과 편의성 사이의 섬세한 균형 맞추기가 필요합니다.

현재 누군가가 디스커스(Discourse) 백업을 탈취하더라도 포럼의 모든 데이터는 얻게 되지만, 라이브 포럼에 로그인할 수는 없습니다. 비밀번호는 해시 처리되어 있고, API 키도 해시 처리되어 있으며, 세션 쿠키는 암호화되어 있기 때문입니다.

백업에 시크릿을 포함하게 되면, 백업을 소지한 누구든 라이브 포럼에 접근하여 피싱, 사기 등을 자행할 수 있게 됩니다.

훌륭합니다! redis 시크릿 키에서 app.yml 시크릿 키로 마이그레이션하는 방법을 메타(Meta)에서 설명하는 주제를 여는 것에 완전히 개방되어 있습니다. ‘서버를 다른 곳으로 이전하기’ 주제에서 링크할 수도 있겠네요.

제 생각에는 기본 백업의 보안도 개선되어야 합니다. 비밀번호와 세션이 해시되어 보호될 수 있지만, 개인 메시지 등에 여전히 기밀로 유지되어야 할 많은 다른 데이터가 있을 수 있습니다. 특히 우리 커뮤니티 포럼에서는 전화번호와 주소를 공개된 곳에 올리는 대신, 개인 메시지를 통해 연락처를 교환하고 판매나 수령을 조율하도록 권장하고 있다는 점을 특히 유의해 주세요.

저는 백업에 대해 인스턴스에 진입하여 백업을 생성한 후, 즉시 gpg를 사용하여 공개 키로 암호화하는 방식을 취하고 있습니다. 이렇게 하면 해당 개인 키를 가진 사람이 아닌 누구에게든 백업이 무용지물이 되며, 저는 이 개인 키를 서버 밖에서 패스프레이즈로 보호하여 보관하고 있습니다.

그럼에도 불구하고, 세션의 시크릿 키가 변경되지 않는다면 한 번만 백업하면 되므로, 이를 위한 간단한 절차만 있으면 충분합니다. 아마도 위에서는 바로 그런 내용을 설명해 주셨을 것입니다.

한 번 시도해 보고 그 주제를 만들어 드릴 수 있는지 확인해 보겠습니다 :slight_smile:

정말 도움 됐어요, @david! 감사합니다!

Discourse에는 개인 메시지(private messages) 기능이 없으며, 해당 기능은 '개인 메시지(Personal Messages)'라고 불립니다. 이 구분은 매우 중요하며, 프라이버시(privacy)를 암시하지 않습니다.

관리자는 암호화가 사용되지 않는 한 사이트의 모든 개인 메시지를 이미 읽을 수 있습니다.

좋은 지적입니다. 하지만 회원들이 개인 정보를 교환하거나 공개하고 싶지 않은 내용을 공유하기 위해 개인 메시지(PM)를 사용할 수 있다는 사실은 변하지 않습니다. 따라서 합리적인 범위 내에서 이러한 데이터를 보호하는 것은 중요합니다.

네, 우리가 사용하는 모든 사이트의 관리자를 신뢰해야 합니다. ProtonMail과 같은 사이트에서도 마찬가지입니다.

조금 주제에서 벗어난 이야기지만… Discourse Encrypt (deprecated) 링크에서 ‘진정으로 사적인’ 메시지를 위한 방법을 알아볼 수 있을지도 모릅니다. 이렇게 하면 암호화된 개인 메시지의 유출되거나 도난당한 백업도 공격자가 읽을 수 없게 됩니다.

(물론, 말씀하신 대로 관리자를 신뢰한다는 전제가 여전히 남아 있습니다)

@david - 다음 게시물을 확인해서 괜찮으면 분리해서 #howto로 이동해 줄 수 있을까요? (거기서 주제를 만들 수 없어요. 그리고 Akismet이 게시물을 숨겼으니 그것도 수정이 필요합니다 :blush:)

@david - 문제를 해결해 주시고 조언까지 해주셔서 정말 감사합니다. 다른 분들에게도 도움이 되길 바랍니다. 세션을 유지하면서 마이그레이션을 할 수 있게 되어서 우리 입장에서는 정말 안도입니다 :partying_face: