diff --git a/src/shrpx.cc b/src/shrpx.cc index ddfde86e..d58e7276 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -2576,7 +2576,8 @@ int main(int argc, char **argv) { } } - if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED) { + if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED && + get_config()->forwarded_by_obfuscated.empty()) { std::random_device rd; std::mt19937 gen(rd()); auto &dst = mod_config()->forwarded_by_obfuscated; diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 2bb31241..67bf9e50 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -406,9 +406,13 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, if ((get_config()->forwarded_params & FORWARDED_FOR) && get_config()->forwarded_for_node_type == FORWARDED_NODE_OBFUSCATED) { - forwarded_for_obfuscated_ = "_"; - forwarded_for_obfuscated_ += util::random_alpha_digit( - worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH); + if (get_config()->forwarded_for_obfuscated.empty()) { + forwarded_for_obfuscated_ = "_"; + forwarded_for_obfuscated_ += util::random_alpha_digit( + worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH); + } else { + forwarded_for_obfuscated_ = get_config()->forwarded_for_obfuscated; + } } } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index a6d2fd19..75bacadf 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -638,7 +638,18 @@ int parse_forwarded_node_type(const std::string &optarg) { return FORWARDED_NODE_IP; } - return -1; + if (optarg.size() < 2 || optarg[0] != '_') { + return -1; + } + + if (std::find_if_not(std::begin(optarg), std::end(optarg), [](char c) { + return util::is_alpha(c) || util::is_digit(c) || c == '.' || c == '_' || + c == '-'; + }) != std::end(optarg)) { + return -1; + } + + return FORWARDED_NODE_OBFUSCATED; } } // namespace @@ -2083,7 +2094,8 @@ int parse_config(const char *opt, const char *optarg, auto type = parse_forwarded_node_type(optarg); if (type == -1) { - LOG(ERROR) << opt << ": unknown node type " << optarg; + LOG(ERROR) << opt << ": unknown node type or illegal obfuscated string " + << optarg; return -1; } @@ -2091,10 +2103,16 @@ int parse_config(const char *opt, const char *optarg, case SHRPX_OPTID_FORWARDED_BY: mod_config()->forwarded_by_node_type = static_cast(type); + if (optarg[0] == '_') { + mod_config()->forwarded_by_obfuscated = optarg; + } break; case SHRPX_OPTID_FORWARDED_FOR: mod_config()->forwarded_for_node_type = static_cast(type); + if (optarg[0] == '_') { + mod_config()->forwarded_for_obfuscated = optarg; + } break; } diff --git a/src/shrpx_config.h b/src/shrpx_config.h index b360cc06..a25205fe 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -306,6 +306,10 @@ struct Config { // obfuscated value used in "by" parameter of Forwarded header // field. std::string forwarded_by_obfuscated; + // obfuscated value used in "for" parameter of Forwarded header + // field. This is only used when user defined static obfuscated + // string is provided. + std::string forwarded_for_obfuscated; std::chrono::seconds tls_session_timeout; ev_tstamp http2_upstream_read_timeout; ev_tstamp upstream_read_timeout;