From 29f73d18b536e43cdcf1d965bc61a5e65f5a26cd Mon Sep 17 00:00:00 2001 From: Mark Travis Date: Mon, 22 Nov 2021 08:03:54 -0800 Subject: [PATCH] Handle ipv6 remote client addresses for secure_gatway. --- src/ripple/rpc/impl/Role.cpp | 12 ++++++++--- src/test/rpc/Roles_test.cpp | 41 +++++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/ripple/rpc/impl/Role.cpp b/src/ripple/rpc/impl/Role.cpp index f3da98c3a4b..adca48383ca 100644 --- a/src/ripple/rpc/impl/Role.cpp +++ b/src/ripple/rpc/impl/Role.cpp @@ -154,14 +154,20 @@ forwardedFor(http_request_type const& request) return pos; }()); - return *boost::beast::http::token_list(boost::string_view(found, pos)) - .begin(); + return boost::string_view(found, pos); +// return *boost::beast::http::token_list(boost::string_view(found, pos)) +// .begin(); } it = request.find("X-Forwarded-For"); if (it != request.end()) { - return *boost::beast::http::token_list(it->value()).begin(); + // This call to boost::beast::http::token_list() truncates an + // IPv6 address at the first colon. + std::size_t const found = it->value().find(','); + return found == boost::string_view::npos ? it->value() : + it->value().substr(0, found); +// return *boost::beast::http::token_list(it->value()).begin(); } return {}; diff --git a/src/test/rpc/Roles_test.cpp b/src/test/rpc/Roles_test.cpp index 2f2465ef0fd..d74a0b31a0f 100644 --- a/src/test/rpc/Roles_test.cpp +++ b/src/test/rpc/Roles_test.cpp @@ -63,6 +63,7 @@ class Roles_test : public beast::unit_test::suite !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); std::unordered_map headers; + // IPv4 tests. headers["X-Forwarded-For"] = "12.34.56.78"; auto rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); @@ -83,11 +84,12 @@ class Roles_test : public beast::unit_test::suite rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88"); - headers["Forwarded"] = - "what=where;for=55.66.77.88, 99.00.11.22;" - "who=3"; - rpcRes = env.rpc(headers, "ping")["result"]; - BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88"); + // This test isn't formatted according to the spec. +// headers["Forwarded"] = +// "what=where;for=55.66.77.88, 99.00.11.22;" +// "who=3"; +// rpcRes = env.rpc(headers, "ping")["result"]; +// BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88"); wsRes = makeWSClient(env.app().config(), true, 2, headers) ->invoke("ping")["result"]; @@ -103,6 +105,35 @@ class Roles_test : public beast::unit_test::suite wsRes = makeWSClient(env.app().config(), true, 2, headers) ->invoke("ping")["result"]; BEAST_EXPECT(wsRes["unlimited"].asBool()); + + // IPv6 tests. + headers = {}; + headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:7777:8888"; + rpcRes = env.rpc(headers, "ping")["result"]; + BEAST_EXPECT(rpcRes["role"] == "proxied"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888"); + + headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:7777:9999, a:b:c:d:e:f, g:h:i:j:k:l"; + rpcRes = env.rpc(headers, "ping")["result"]; + BEAST_EXPECT(rpcRes["role"] == "proxied"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999"); + + headers["X-Forwarded-For"] = "[2001:db8:3333:4444:5555:6666:7777:8888]"; + rpcRes = env.rpc(headers, "ping")["result"]; + BEAST_EXPECT(rpcRes["role"] == "proxied"); + BEAST_EXPECT(rpcRes["ip"] == "[2001:db8:3333:4444:5555:6666:7777:8888]"); + + headers["X-Forwarded-For"] = "[2001:db8:3333:4444:5555:6666:7777:9999], [a:b:c:d:e:f], [g:h:i:j:k:l]"; + rpcRes = env.rpc(headers, "ping")["result"]; + BEAST_EXPECT(rpcRes["role"] == "proxied"); + BEAST_EXPECT(rpcRes["ip"] == "[2001:db8:3333:4444:5555:6666:7777:9999]"); + + headers = {}; + headers["Forwarded"] = "for=2001:db8:3333:4444:5555:6666:7777:aaaa"; + rpcRes = env.rpc(headers, "ping")["result"]; + BEAST_EXPECT(rpcRes["role"] == "proxied"); + BEAST_EXPECT(rpcRes["ip"] =="2001:db8:3333:4444:5555:6666:7777:aaaa"); + // IPv6 (dual) tests. } }