익명 사용자의 CDN 비호환 파일 다운로드 방지

제 사이트에서 mp4 파일이 404 오류를 반환하고 있습니다.

authorized_extensions가 *로 설정되어 있습니다. 파일 업로드는 정상적으로 이루어지며 파일 시스템에서도 해당 파일을 확인할 수 있습니다. 권한도 올바르게 설정되어 있고, file 명령어로 확인했을 때 MP4 파일임이 분명합니다. Rails의 레코드도 정상적으로 보입니다:

[1] pry(main)> u=Upload.find(196082)
=> #<Upload:0x00005601a1b56348
 id: 196082,
 user_id: 1,
 original_filename: "PXL_20220617_184736219.mp4",
 filesize: 9328093,
 width: nil,
 height: nil,
 url: "/uploads/default/original/3X/5/6/5679d94dfce852f780afa5fcb7f1a29d810cc8fc.mp4",
 created_at: Fri, 17 Jun 2022 18:53:41.130790000 UTC +00:00,
 updated_at: Fri, 17 Jun 2022 18:53:41.176664000 UTC +00:00,
 sha1: "5679d94dfce852f780afa5fcb7f1a29d810cc8fc",
 origin: nil,
 retain_hours: nil,
 extension: "mp4",
 thumbnail_width: nil,
 thumbnail_height: nil,
 etag: nil,
 secure: false,
 access_control_post_id: nil,
 original_sha1: nil,
 verification_status: 1,
 animated: nil,
 security_last_changed_at: nil,
 security_last_changed_reason: nil>

하지만 해당 파일에 접근하면 404가 반환됩니다. 최근 mp4 관련해서 몇 가지 새로운 기능과 버그 수정이 이루어졌지만, 방금 업그레이드를 진행했음에도 여전히 작동하지 않습니다. 어디서부터 확인해야 할지 모르겠습니다.

문제는 nginx 설정이 특정 파일 유형만 허용하고 있다는 것입니다. 이를 버그로 이동합니다.

discourse.conf에는 다음과 같은 스탠사가 있습니다:

      # this allows us to bypass rails
      location ~* \.(gif|png|jpg|jpeg|bmp|tif|tiff|ico|webp)$ {
          add_header Access-Control-Allow-Origin *;
          try_files $uri =404;
      }

컨테이너 내부의 discourse.conf에 mp3와 mp4를 파일 유형에 추가했습니다(webp 뒤에 추가했으며, 이제 mp4가 정상적으로 작동합니다). discourse_docker의 config/nginx.sample.conf에서 "bypass rails"를 확인할 수 있습니다. 하지만 이것이 도커 내부 템플릿에 어떻게 반영되는지 알 수 없어, 이 상황이 언제 발생했는지 파악하는 방법을 모릅니다.

허용된 파일 유형으로 *가 지정되어 있습니다. 사이트 설정에 나열된 경우 mp3/mp4가 작동하도록 하는 어떤 마법이 있는지 모르겠지만, 그렇게 될 수 있는 방법을 알 수 없습니다.

Rails를 우회하지 않는 한 다운로드가 정상적으로 작동해야 합니다.

해당 라우트가 있습니다.

get "uploads/:site/original/:tree:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, tree: /([a-z0-9]+\/)+/i, sha: /\h{40}/, extension: /[a-z0-9\._]+/i }

그리고 show 메서드가 파일을 보내도록 되어 있습니다. nginx 설정은 Rails를 우회하여 효율성을 높일 뿐이지만, 이는 필수 요건이 아닙니다.

아.. authorized_extensions는 업로드 인증에만 사용되며 다운로드에는 해당하지 않습니다(즉, 해당 목록에 없는 확장자는 파일 다운로드를 막지 않아야 합니다).

최신 tests-passed 환경에서는 재현이 불가능하므로 #support로 다시 이동해 보시는 것이 좋을 것 같습니다 :slight_smile:

수정: 해당 사이트를 검색해 보니 다른 문제들도 있는 것 같습니다.

이제 파일을 단순히 wget으로 가져오면 작동합니다.

(수정 2: 이는 nginx 설정에 mp4 확장자를 추가했기 때문일 수 있습니다? 그래도 제 환경에서는 바로 작동합니다)

감사합니다! 그걸 가장 먼저 확인해 볼게요. 안전 모드를 시도해 봤어야 했는데 말이죠!

그 서비스 워커 때문에 좀 혼란스럽네요.

버그가 아닙니다.

아직도 그 Service Worker 메시지를 이해하지 못하지만, prevent_anons_from_downloading_files를 끄니 이제 작동합니다. “prevent_anons” 설정이 CDN과 호환되지 않는 것 같습니다.

하지만 해당 사이트에서 업로드된 파일이 CDN에서 가져와지지 않는 것 아닌가요? 그냥 www의 위치를 참조하고 있을 뿐입니다.

그렇다면 저는 오히려 더 혼란스럽습니다. 아마 CDN이 정의된 후 해당 게시글이 다시 처리(rebake)되지 않은 것 같습니다.

하지만 https://www.turiver.com/t/argentina-la-sociedad-perdida/117158/7909는 CDN에서 로드되고 있으며, 설정을 변경하니 문제가 해결되었습니다.

콘솔에서 404 오류가 여러 개 뜨는 것도 보이는데, 해당 사이트는 표준 2컨테이너 구성이며 다음 플러그인만 설치되어 있습니다:

          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-akismet.git
          - git clone https://github.com/discourse/discourse-spoiler-alert.git
          - git clone https://github.com/discourse/discourse-chat-integration.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-cakeday.git
          - git clone https://github.com/discourse/discourse-data-explorer.git
          - git clone https://github.com/discourse/discourse-checklist.git
          - git clone https://github.com/discourse/discourse-canned-replies.git
          - git clone https://github.com/discourse/discourse-chat

그리고 제가 보는 https://www.turiver.com/t/argentina-la-sociedad-perdida/117158/8017은 로그인 여부와 관계없이 CDN에서 가져오는 것으로 보입니다.