Backport of 'Fall back across resolved IPs in Gitlab::HTTP (Dependency Proxy 599)'

What does this MR do and why?

Backport of !239733 (merged) into 19-2-stable-ee.

Gitlab::HTTP resolves a host to all of its IP addresses, but only ever connects to the first one. The address is pinned at validation time so that DNS rebinding can't swap it out later. If that first address happens to be unreachable, typically a black-holed IPv6 record on a dual-stack network, the connection attempt hangs until it times out and nothing else is tried. The Dependency Proxy converts that timeout into an HTTP 599, so the CI job fails to pull its image. Retrying doesn't help, because the retry picks the same dead address.

After this change, connect walks the remaining validated addresses instead of giving up on the first one. Only addresses that already passed validate_local_request are offered, so an allow-listed host can't leak a co-resolved private or loopback address. Candidates are capped at one per address family, and only unreachable errors trigger a fallback: a refused or reset connection still surfaces as it did before.

This does not help when the upstream is unreachable at every resolved address. That still ends in a 599.

Scope

Straight cherry-pick of 29746059, applied with no conflicts and no modifications. Confined to gems/gitlab-http: no application code, no migrations, no change to how single-address connections behave.

Test plan

cd gems/gitlab-http
bundle exec rspec

Passing locally against this branch: 467 examples, 0 failures. That includes the four new examples in spec/gitlab/http_v2/ip_fallback_spec.rb, which cover falling back past an unreachable first address, raising when every address is unreachable, surfacing a refused connection without falling back, and refusing to fall back to a co-resolved loopback address for an allow-listed host.

Credit

Authored by @trilamsr, who wrote and landed the original fix on master and opened !254382 (closed) as a backport. That MR targeted master rather than the stable branch, because contributors can't push to protected stable branches, which made its diff show 530 files. This MR carries the same commit with the correct target branch and preserves the original authorship.

References

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

  • This MR is backporting a bug fix, documentation update, or spec fix, previously merged in the default branch.
  • The MR that fixed the bug on the default branch has been deployed to GitLab.com (not applicable for documentation or spec changes).
  • The MR title is descriptive (e.g. "Backport of 'title of default branch MR'"). This is important, since the title will be copied to the patch blog post.
  • Required labels have been applied to this merge request
  • This MR has been approved by a maintainer (only one approval is required).
  • Ensure the e2e:test-on-omnibus-ee job has succeeded, or if it has failed, investigate the failures. If you determine the failures are unrelated, you may proceed. If you need assistance investigating, request help in the #s_developer_experience Slack channel to confirm the failures are unrelated to the merge request.

Note to the merge request author and maintainer

If you have questions about the patch release process, please:

Edited by Radamanthus Batnag

Merge request reports

Loading
Loading