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 validating the downstream ip of the connection #108

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

kmala
Copy link

@kmala kmala commented Apr 18, 2024

fixes #107
Had to change the PolicyFunc mentod signature as i couldn't find a better way to handle policy if we have separate functions for upstream and downstream and if both are present.

@dims
Copy link

dims commented Apr 18, 2024

@pires can you please approve the CI workflow so we can check if the new test being added works fine? thanks!

@coveralls
Copy link

coveralls commented Apr 18, 2024

Coverage Status

coverage: 95.119% (+0.1%) from 95.017%
when pulling 9dc11aa on kmala:feat
into 8a2480a on pires:main.

@pires
Copy link
Owner

pires commented Apr 18, 2024

@dims for you the world, thanks for pinging.

@dims
Copy link

dims commented Apr 18, 2024

@kmala please review the coverage tests, looks like we need to make sure they don't regress.

@kmala
Copy link
Author

kmala commented Apr 18, 2024

please review the coverage tests, looks like we need to make sure they don't regress.

Update and verified locally that the coverage has increased.

policy.go Outdated
@@ -43,7 +44,7 @@ const (
// Kubernetes pods local traffic. The def is a policy to use when an upstream
// address doesn't match the skipHeaderCIDR.
func SkipProxyHeaderForCIDR(skipHeaderCIDR *net.IPNet, def Policy) PolicyFunc {
return func(upstream net.Addr) (Policy, error) {
return func(upstream net.Addr, downstream net.Addr) (Policy, error) {
Copy link
Owner

Choose a reason for hiding this comment

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

This breaks the API and I'm thinking there's no need to do this. upstream is just a placeholder for any net.Addr so unless both upstream and downstream addresses have to be evaluated in a policy, I think we can just keep the API as is, maybe rename upstream to address and the new PolicyFunc just works. WDYT?

Copy link
Author

Choose a reason for hiding this comment

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

I thought about it and the issue i faced is where this function is called https://github.com/pires/go-proxyproto/blob/main/protocol.go#L71. If we have 2 policy function one calling with the remote and other with the local address, then i felt its not straight forward on handling different policy returned when both the functions are used.
I can change it if we are okay with second function overriding if both are set.

Copy link
Author

Choose a reason for hiding this comment

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

@pires what do you suggest as i don't see any other option apart from these?

Copy link
Owner

Choose a reason for hiding this comment

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

I'm thinking if anything, we'd split PolicyFunc into DownstreamPolicyFunc and UpstreamPolicyFunc with the same signature. My only strong opinion is not wanting to break the API.

Copy link
Owner

Choose a reason for hiding this comment

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

@emersion got any thoughts on this? 🙏🏻

Copy link
Author

Choose a reason for hiding this comment

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

Yes, i understand that. Do we want to have one function override the other if both are present or do we want to pick a stricter policy of both(which i think is bit difficult to say which is stricter)

protocol.go Outdated
@@ -68,7 +68,7 @@ func (p *Listener) Accept() (net.Conn, error) {

proxyHeaderPolicy := USE
if p.Policy != nil {
proxyHeaderPolicy, err = p.Policy(conn.RemoteAddr())
proxyHeaderPolicy, err = p.Policy(conn.RemoteAddr(), conn.LocalAddr())
Copy link
Owner

Choose a reason for hiding this comment

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

I see now what the problem is. Let me think a little bit more about this. We'll find agreement.

Copy link
Author

Choose a reason for hiding this comment

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

sure 👍

Copy link
Author

Choose a reason for hiding this comment

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

@pires did you get a chance to look more into this?

@emersion
Copy link
Contributor

If we don't want to break the API, my take would be to add a new ConnPolicy callback:

  • Only one of Policy and ConnPolicy can be specified, not both, to avoid having to pick between the two.
  • ConnPolicy takes the net.Conn so that it can fetch any details it needs about the connection. Alternatively, it takes a ConnPolicyOptions struct which carry the IP addresses and can be extended later with more fields.

@kmala
Copy link
Author

kmala commented May 25, 2024

Only one of Policy and ConnPolicy can be specified, not both, to avoid having to pick between the two.

The issue is that since the Listener is exported https://github.com/pires/go-proxyproto/blob/main/protocol.go#L25 there is no proper way to enforce that only one of the policy/connpolicy can be specified.

We can just ignore Policy if ConnPolicy is specified in the code but that won't be obvious unless someone reads the code or comments.

@emersion
Copy link
Contributor

It should be possible to panic from Accept if the library user provides both. Not ideal, but still better than silently ignoring one of the callbacks IMHO.

@kmala
Copy link
Author

kmala commented Jun 4, 2024

@emersion can you please check if the changes look good?

@pires
Copy link
Owner

pires commented Jun 5, 2024

I am thinking the ConnPolicy should become the new API, since it seems to encapsulate what Policy is doing today, and we'd mark Policy as deprecated and to be removed in a future release. WDYT?

@kmala
Copy link
Author

kmala commented Jun 5, 2024

I am thinking the ConnPolicy should become the new API, since it seems to encapsulate what Policy is doing today, and we'd mark Policy as deprecated and to be removed in a future release. WDYT?

Update the field as deprecated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Support for policy on local address
5 participants