maybe-finance / maybe

The OS for your personal finances
https://maybe.co
GNU Affero General Public License v3.0
30.1k stars 2.26k forks source link

Bug: Unable to run through reverse proxy #1205

Open RobHofmann opened 6 days ago

RobHofmann commented 6 days ago

Describe the bug Getting an error when running through a reverse proxy like Traefik

To Reproduce Steps to reproduce the behavior:

  1. Setup maybe
  2. Setup reverse proxy in front of Maybe
  3. Get errors like the one pasted below.

Expected behavior Get a normal 200 OK response.

Additional context

I, [2024-09-24T12:12:12.192943 #1]  INFO -- : [b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] Completed 422 Unprocessable Content in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)
E, [2024-09-24T12:12:12.193983 #1] ERROR -- : [b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5]
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] ActionController::InvalidAuthenticityToken (The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that
refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
best solution is to change your referrer policy to something less strict like same-origin or strict-origin.
If you cannot change the referrer policy, you can disable origin checking with the
Rails.application.config.action_controller.forgery_protection_origin_check setting.
):
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5]
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/request_forgery_protection.rb:628:in `valid_request_origin?'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/request_forgery_protection.rb:463:in `verified_request?'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/request_forgery_protection.rb:392:in `verify_authenticity_token'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:362:in `block in make_lambda'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:179:in `block in call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:180:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:559:in `block in invoke_before'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:559:in `each'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:559:in `invoke_before'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:119:in `block in run_callbacks'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:141:in `run_callbacks'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/abstract_controller/callbacks.rb:260:in `process_action'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/rescue.rb:27:in `process_action'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:77:in `block in process_action'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/notifications.rb:210:in `block in instrument'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/notifications.rb:210:in `instrument'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/instrumentation.rb:76:in `process_action'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activerecord (7.2.1) lib/active_record/railties/controller_runtime.rb:39:in `process_action'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/abstract_controller/base.rb:163:in `process'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionview (7.2.1) lib/action_view/rendering.rb:40:in `process'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal.rb:252:in `dispatch'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_controller/metal.rb:335:in `dispatch'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/routing/route_set.rb:67:in `dispatch'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/routing/route_set.rb:50:in `serve'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/journey/router.rb:53:in `block in serve'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/journey/router.rb:133:in `block in find_routes'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/journey/router.rb:126:in `each'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/journey/router.rb:126:in `find_routes'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/journey/router.rb:34:in `serve'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/routing/route_set.rb:896:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rails-settings-cached (2.9.4) lib/rails-settings/middleware.rb:9:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/tempfile_reaper.rb:20:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/etag.rb:29:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/conditional_get.rb:43:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/head.rb:15:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/http/content_security_policy.rb:36:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack-session (2.0.0) lib/rack/session/abstract/id.rb:272:in `context'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack-session (2.0.0) lib/rack/session/abstract/id.rb:266:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/cookies.rb:704:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/callbacks.rb:31:in `block in call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] activesupport (7.2.1) lib/active_support/callbacks.rb:101:in `run_callbacks'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/callbacks.rb:30:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] sentry-rails (5.19.0) lib/sentry/rails/rescued_exception_interceptor.rb:9:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:31:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] sentry-ruby (5.19.0) lib/sentry/rack/capture_exceptions.rb:15:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/show_exceptions.rb:32:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] railties (7.2.1) lib/rails/rack/logger.rb:41:in `call_app'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] railties (7.2.1) lib/rails/rack/logger.rb:29:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/remote_ip.rb:96:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/request_id.rb:33:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/method_override.rb:28:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/runtime.rb:24:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/executor.rb:16:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] actionpack (7.2.1) lib/action_dispatch/middleware/static.rb:27:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] rack (3.1.7) lib/rack/sendfile.rb:114:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] railties (7.2.1) lib/rails/engine.rb:535:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/configuration.rb:272:in `call'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/request.rb:100:in `block in handle_request'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/thread_pool.rb:378:in `with_force_shutdown'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/request.rb:99:in `handle_request'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/server.rb:464:in `process_client'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/server.rb:245:in `block in run'
[b7efda6d-7d18-4f07-a6a7-bd981f9d4fb5] puma (6.4.2) lib/puma/thread_pool.rb:155:in `block in spawn_thread'
I, [2024-09-24T12:12:12.262812 #1]  INFO -- : Finished "/cable" [WebSocket] for 192.168.2.54 at 2024-09-24 12:12:12 +0000
I, [2024-09-24T12:12:12.263028 #1]  INFO -- : Turbo::StreamsChannel stopped streaming from Z2lkOi8vbWF5YmUvRmFtaWx5LzNlYzMxOTNiLTZmMzktNGRlYS04OTM3LWRlMTJkNGNmM2IwNQ:notifications
I, [2024-09-24T12:12:12.263170 #1]  INFO -- : Turbo::StreamsChannel stopped streaming from Z2lkOi8vbWF5YmUvRmFtaWx5LzNlYzMxOTNiLTZmMzktNGRlYS04OTM3LWRlMTJkNGNmM2IwNQ
zachgoll commented 6 days ago

@RobHofmann are you passing headers?

https://github.com/maybe-finance/maybe/issues/979#issuecomment-2233979007

For example, with Nginx:

location / {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}
RobHofmann commented 8 hours ago
    maybe-finance:
      rule: "Host(`maybe-finance.domain.local`)"
      service: maybe-finance@file
      tls: {}
      entryPoints:
      - https
      middlewares:
      - referrerPolicy
      - compress
      - ipWhitelisting
  middlewares:
    referrerPolicy:
      headers:
        referrerPolicy: "no-referrer"
    compress:
      compress: {}
    ipWhitelisting:
      ipAllowList:
        sourceRange:
        - 192.168.0.0/19
        - 192.168.32.0/24
        - 192.168.33.0/24
        - 172.16.0.0/12
  services:
    maybe-finance:
      loadBalancer:
        passHostHeader: true
        servers:
          - url: http://maybe-finance:3000

This is how I have my config (which works for about 50 other applications). Do I need to do something special for this app?

zachgoll commented 2 hours ago

@RobHofmann it looks like this may be the cause of this:

middlewares:
  referrerPolicy:
    headers:
      referrerPolicy: "no-referrer"

I think if you switch this to referrerPolicy: "same-origin" it should fix the issue.

By default, Rails uses the Referer header to make sure the POST request is coming from the same origin as the app. If it is disabled like this, it will receive a null origin and throw this error as a way to protect against CSRF attacks.

Are you running other Rails apps successfully with this configuration? I would expect this configuration to throw this error in most Rails apps by default.