Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for the PROXY protocol (v1 only) #2654

Merged
merged 4 commits into from Sep 7, 2021

Conversation

Roguelazer
Copy link
Contributor

Description

This adds support for parsing the PROXY Protocol (version 1 only). It's behind the set_remote_address feature when invoked like set_remote_address proxy_protocol: :v1. I put the v1 in there in case some bold soul wants to add v2 support at some point.

This gracefully handles the case where the client doesn't send the PROXY protocol and falls back to normal logic.

Closes #2651

Your checklist for this pull request

  • I have reviewed the guidelines for contributing to this repository.
  • I have added (or updated) appropriate tests if this PR fixes a bug or adds a feature.
  • My pull request is 100 lines added/removed or less so that it can be easily reviewed.
  • If this PR doesn't need tests (docs change), I added [ci skip] to the title of the PR.
  • If this closes any issues, I have added "Closes #issue" to the PR description or my commit messages.
  • I have updated the documentation accordingly.
  • All new and existing tests passed, including Rubocop.

Copy link
Member

@dentarg dentarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR makes it 5

# There are 4 possible values:

lib/puma/dsl.rb Outdated Show resolved Hide resolved
lib/puma/dsl.rb Outdated Show resolved Hide resolved
@Roguelazer Roguelazer mentioned this pull request Jul 2, 2021
@nateberkopec nateberkopec added feature waiting-for-review Waiting on review from anyone labels Jul 5, 2021
@Roguelazer
Copy link
Contributor Author

I don't think any of the CI failures are related to my commit...

@dentarg
Copy link
Member

dentarg commented Jul 7, 2021

I don't think any of the CI failures are related to my commit...

I started a re-run of CI (edit: started them again, tests be flaky as this branch passed in my fork)

@Roguelazer
Copy link
Contributor Author

I found a bug in this in my own testing: on about 0.0025% of requests, parsing fails with Puma::HttpParserError: Requested start is after data buffer end.

It turns out that this happens when the initial read on the socket returned the PROXY protocol header and only the PROXY protocol header (which depends on TCP_CORK and a bunch of other stuff on the client side, but is easily reproducible by hand). This is because if you call @parser.execute with a 0-byte buffer, it fails.

I'm going to push an update to this branch that ensures we don't do that.

…rt reads

The HTTP parser requires that the buffer be non-empty when it's invoked,
but if the entire buffer was the PROXY protocol, we may sometimes invoke
it with an empty buffer. This causes the following error:

  Puma::HttpParserError: Requested start is after data buffer end.

The fix? Any time we consume the entire buffer for the PROXY protocol,
simply return `false` to indicate that we require more data.
@Roguelazer
Copy link
Contributor Author

This is good to be reviewed, for what it's worth

@nateberkopec
Copy link
Member

Just commenting to say I haven't forgotten about this. This is up for review by anyone other than the original author (we allow code review from anyone as we discuss in CONTRIBUTING.md)

@nateberkopec
Copy link
Member

Putting out to the puma-contrib channel that I want one more review on this but I think this would be a great addition for the next release

Copy link
Member

@dentarg dentarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! I tried it out with this HAProxy config:

defaults
    timeout connect 10s
    timeout client 30s
    timeout server 30s
    # send everything to stdout
    log stdout format raw daemon

frontend www
    bind *:4444
    use_backend proxy

frontend www2
    bind *:5555
    use_backend noproxy

backend proxy
    mode http
    server server1 127.0.0.1:9292 send-proxy

backend noproxy
    mode tcp
    server server1 127.0.0.1:9292

@nateberkopec
Copy link
Member

Thanks for the review @dentarg!

@nateberkopec nateberkopec merged commit 656f0f7 into puma:master Sep 7, 2021
JuanitoFatas pushed a commit to JuanitoFatas/puma that referenced this pull request Sep 9, 2022
* add support for the PROXY protocol (v1 only)

* slightly simplify test

* address review feedback

* move PROXY protocol parsing into its own method; avoid issue with short reads

The HTTP parser requires that the buffer be non-empty when it's invoked,
but if the entire buffer was the PROXY protocol, we may sometimes invoke
it with an empty buffer. This causes the following error:

  Puma::HttpParserError: Requested start is after data buffer end.

The fix? Any time we consume the entire buffer for the PROXY protocol,
simply return `false` to indicate that we require more data.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature waiting-for-review Waiting on review from anyone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PROXY Protocol
3 participants