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 rspecPassing 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
- Issue: #560575
- Default branch MR: !239733 (merged)
- Contributor's backport attempt: !254382 (closed)
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
- severity label and bug subtype labels (if applicable)
- If this MR fixes a bug that affects customers, the customer label has been applied.
- This MR has been approved by a maintainer (only one approval is required).
- Ensure the
e2e:test-on-omnibus-eejob 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:
- Refer to the patch release runbook for engineers and maintainers for guidance.
- Ask questions on the
#releasesSlack channel (internal only). - Once the backport has been merged, the commit changes will be automatically deployed to a release environment that can be used for manual validation. See after merging runbook for details.