Skip to content

feat(engine): add trustedproxies and remoteIP - #2632

Merged
appleboy merged 24 commits into
masterfrom
fix-client-ip-cve
Apr 6, 2021
Merged

feat(engine): add trustedproxies and remoteIP#2632
appleboy merged 24 commits into
masterfrom
fix-client-ip-cve

Conversation

@manucorporat

@manucorporat manucorporat commented Feb 7, 2021

Copy link
Copy Markdown
Contributor

TODO:

  • add new tests
  • fix tests

@codecov

codecov Bot commented Feb 7, 2021

Copy link
Copy Markdown

Codecov Report

Merging #2632 (9018d58) into master (f3de813) will increase coverage by 0.03%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2632      +/-   ##
==========================================
+ Coverage   98.64%   98.67%   +0.03%     
==========================================
  Files          41       41              
  Lines        1990     2038      +48     
==========================================
+ Hits         1963     2011      +48     
  Misses         15       15              
  Partials       12       12              
Impacted Files Coverage Δ
context.go 97.64% <100.00%> (+0.13%) ⬆️
gin.go 99.12% <100.00%> (+0.11%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f3de813...9018d58. Read the comment docs.

Comment thread gin.go Outdated
Comment thread README.md
Comment thread context.go
return ip
}
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

			if !cidr.Contains(remoteIP) {
                             continue
                         }
			for _, headerName := range c.engine.RemoteIPHeaders {
				ip, valid := validateHeader(c.requestHeader(headerName))
				if valid {
					return ip
				}
			}

suggestion, thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

refactored it a little bit, review again... now thee logic is better separated between validating the trusted proxy and parsing the header, also a nw AP

ip, trusted = c.RemoteIP()

allows to even implement your own logic, or trust othe headers that might not be even related with IP!

@agmt agmt Aug 24, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do you expect that HTTP proxy running on c.RemoteIP() resets X-Forwarded-For? Because if it appends, then we can't inherit trustiness of c.RemoteIP() to all other proxies.

Comment thread context.go Outdated
@RainbowMango

Copy link
Copy Markdown

Hi Forks, would you like to cut a new release after this PR?

@javierprovecho

Copy link
Copy Markdown
Member

@RainbowMango we’ll work towards it, as this PR brings some new properties to gin.engine, the release should be 1.7.0, so I may need some sync with @appleboy and @thinkerou on that milestone.

@RainbowMango

Copy link
Copy Markdown

Thanks for your quick response. I'm looking forward to the new release.

@manucorporat

Copy link
Copy Markdown
Contributor Author

Alright team.

Added a new public API called:

ip, trusted := c.RemoteIP()

this function parsed the remote IP, and checks if it's a trusted proxy OR not.

Then clientIP function logic focuses in using this information and parse the appropriated headers.

Should help to keep logic separated and easier to test as well as a interesting new API, that can be used by developers to use their own logic and for example "trust" other headers.

Thoughts?

@thinkerou

Copy link
Copy Markdown
Member

@appleboy we merge the pr and publish v1.7 now? thanks!

@appleboy

appleboy commented Apr 6, 2021

Copy link
Copy Markdown
Member

@thinkerou Yes, waiting for the final Travis report.

@appleboy
appleboy merged commit bfc8ca2 into master Apr 6, 2021
@appleboy
appleboy deleted the fix-client-ip-cve branch April 6, 2021 03:37
@sorenisanerd

Copy link
Copy Markdown
Contributor

Why even have contribution guidelines if you don't follow them yourselves and ignore other people's contributions?

@sorenisanerd

Copy link
Copy Markdown
Contributor

I mean.. Yeah, sure, that's one way to address a failing test:

https://github.com/sorenisanerd/gin/blob/d0bf406364d992443be33739745d61386fec4044/context_test.go#L1444-L1446

vs

gin/context_test.go

Lines 1431 to 1433 in bfc8ca2

// Only trust RemoteAddr
c.engine.TrustedProxies = []string{"40.40.40.40"}
assert.Equal(t, "20.20.20.20", c.ClientIP())

Also, your 230 days of optimization probably haven't yielded the returns you were hoping for:

gin/context.go

Line 770 in bfc8ca2

trustedCIDRs, _ := c.engine.prepareTrustedCIDRs()

@appleboy

appleboy commented Apr 8, 2021

Copy link
Copy Markdown
Member

data race issue: #2674

@JasonCeng

Copy link
Copy Markdown

Does CVE-2020-28483 have been fixed in gin V1.7.0 and later?

@sorenisanerd

Copy link
Copy Markdown
Contributor

Does CVE-2020-28483 have been fixed in gin V1.7.0 and later?

Nope.

@xpunch

xpunch commented Apr 30, 2021

Copy link
Copy Markdown

Hi guys, thanks for your work. But I meet an issue that ctx.ClientIP() not work cause engine.Run() not called.
My application uses gin as web handler, so it don't need to startup by calling engine.Run(), which makes trustedCIDRs uninitialized. I think I'm not the only one who use gin this way, could you consider move trustedCIDRs initialization into somewhere like a public method, so I can call it when I need if I don't want to call Run().

@xpunch

xpunch commented Apr 30, 2021

Copy link
Copy Markdown
func New() *Engine {
	...
        engine.trustedCIDRs = []*net.IPNet{{IP: net.IP{0x0, 0x0, 0x0, 0x0}, Mask: net.IPMask{0x0, 0x0, 0x0, 0x0}}}
        ...
}

Should also set default value for trustedCIDRs.

@tsmethurst

Copy link
Copy Markdown

Hi guys, thanks for your work. But I meet an issue that ctx.ClientIP() not work cause engine.Run() not called.
My application uses gin as web handler, so it don't need to startup by calling engine.Run(), which makes trustedCIDRs uninitialized. I think I'm not the only one who use gin this way, could you consider move trustedCIDRs initialization into somewhere like a public method, so I can call it when I need if I don't want to call Run().

I need this as well for a use case where I want to shut down the http server nicely; i also don't call Run() and wondered why it wasn't parsing trusted proxies properly... now i see!

@tsmethurst

Copy link
Copy Markdown

Ahh i'm sorry, seems you already added it in here: https://github.com/superseriousbusiness/gin/commit/b5ca9898757b45bbdcc1464b73a12f3ca552f94d

nevermind! :)

@montanaflynn

montanaflynn commented Aug 4, 2021

Copy link
Copy Markdown

This appears to have changed the old behavior, is that correct? I was under the assumption this would be an opt-in change.

How can I just trust all proxies? I'm behind cloudfront and trust their proxies but don't have all their ip addresses.

Comment thread context_test.go

// Only trust RemoteAddr
c.engine.TrustedProxies = []string{"40.40.40.40"}
assert.Equal(t, "20.20.20.20", c.ClientIP())

@agmt agmt Aug 24, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we trust proxy 40.40.40.40, but not trust 30.30.30.30 (proxy it is or not), then ClientIP should be 30.30.30.30 as 20.20.20.20 was set by somebody untrusted.
Please do not forget that X-Forwarded-For is appended, so it should be processed right-to-left:

right-most IP address is the IP address of the most recent proxy and the left-most IP address is the IP address of the originating client.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/bug Found something you weren't expecting? Report it here!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security vulnerability identified with all current releases of gin CVE-2020-28483