nghttpx: Disallow user defined static obfuscated string for "for" parameter

This commit is contained in:
Tatsuhiro Tsujikawa 2016-01-21 21:05:07 +09:00
parent 9ac3e643d8
commit 5a3ca7e700
5 changed files with 33 additions and 43 deletions

View File

@ -140,7 +140,7 @@ func TestH2H1StripAddXff(t *testing.T) {
// Forwarded header field with obfuscated "by" and "for" parameters.
func TestH2H1AddForwardedObfuscated(t *testing.T) {
st := newServerTester([]string{"--add-forwarded=by,for,host,proto"}, t, func(w http.ResponseWriter, r *http.Request) {
pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127.0.0.1:%v";proto=http`, serverPort)
pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127\.0\.0\.1:%v";proto=http`, serverPort)
validFwd := regexp.MustCompile(pattern)
got := r.Header.Get("Forwarded")
@ -164,10 +164,11 @@ func TestH2H1AddForwardedObfuscated(t *testing.T) {
// TestH2H1AddForwardedByIP tests that server generates Forwarded header
// field with IP address in "by" parameter.
func TestH2H1AddForwardedByIP(t *testing.T) {
st := newServerTester([]string{"--add-forwarded=by,for,host,proto", "--forwarded-by=ip", "--forwarded-for=_bravo"}, t, func(w http.ResponseWriter, r *http.Request) {
want := fmt.Sprintf(`by="127.0.0.1:%v";for=_bravo;host="127.0.0.1:%v";proto=http`, serverPort, serverPort)
if got := r.Header.Get("Forwarded"); got != want {
t.Errorf("Forwarded = %v; want %v", got, want)
st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
pattern := fmt.Sprintf(`by="127\.0\.0\.1:%v";for=_[^;]+`, serverPort)
validFwd := regexp.MustCompile(pattern)
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
}
})
defer st.Close()
@ -280,12 +281,14 @@ func TestH2H1StripForwarded(t *testing.T) {
}
// TestH2H1AddForwardedStatic tests that server generates Forwarded
// header field with the given static obfuscated strings for "by" and
// "for" parameters.
// header field with the given static obfuscated string for "by"
// parameter.
func TestH2H1AddForwardedStatic(t *testing.T) {
st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=_alpha", "--forwarded-for=_bravo"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("Forwarded"), `by=_alpha;for=_bravo`; got != want {
t.Errorf("Forwarded = %v; want %v", got, want)
st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
pattern := `by=_alpha;for=_[^;]+`
validFwd := regexp.MustCompile(pattern)
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
}
})
defer st.Close()
@ -1669,12 +1672,13 @@ func TestH2H2StripAddXff(t *testing.T) {
}
// TestH2H2AddForwarded tests that server generates Forwarded header
// field using static obfuscated "by" and "for" parameter.
// field using static obfuscated "by" parameter.
func TestH2H2AddForwarded(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha", "--forwarded-for=_bravo"}, t, func(w http.ResponseWriter, r *http.Request) {
want := fmt.Sprintf(`by=_alpha;for=_bravo;host="127.0.0.1:%v";proto=https`, serverPort)
if got := r.Header.Get("Forwarded"); got != want {
t.Errorf("Forwarded = %v; want %v", got, want)
st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
pattern := fmt.Sprintf(`by=_alpha;for=_[^;]+;host="127\.0\.0\.1:%v";proto=https`, serverPort)
validFwd := regexp.MustCompile(pattern)
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
t.Errorf("Forwarded = %v; want pattern %v", got, pattern)
}
})
defer st.Close()
@ -1692,11 +1696,11 @@ func TestH2H2AddForwarded(t *testing.T) {
}
// TestH2H2AddForwardedMerge tests that server generates Forwarded
// header field using static obfuscated "by" and "for" parameter, and
// header field using static obfuscated "by" parameter, and
// existing Forwarded header field.
func TestH2H2AddForwardedMerge(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha", "--forwarded-for=_bravo"}, t, func(w http.ResponseWriter, r *http.Request) {
want := fmt.Sprintf(`host=foo, by=_alpha;for=_bravo;host="127.0.0.1:%v";proto=https`, serverPort)
st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
want := fmt.Sprintf(`host=foo, by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
if got := r.Header.Get("Forwarded"); got != want {
t.Errorf("Forwarded = %v; want %v", got, want)
}
@ -1719,11 +1723,11 @@ func TestH2H2AddForwardedMerge(t *testing.T) {
}
// TestH2H2AddForwardedStrip tests that server generates Forwarded
// header field using static obfuscated "by" and "for" parameter, and
// header field using static obfuscated "by" parameter, and
// existing Forwarded header field stripped.
func TestH2H2AddForwardedStrip(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-forwarded", "--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha", "--forwarded-for=_bravo"}, t, func(w http.ResponseWriter, r *http.Request) {
want := fmt.Sprintf(`by=_alpha;for=_bravo;host="127.0.0.1:%v";proto=https`, serverPort)
st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-forwarded", "--add-forwarded=by,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) {
want := fmt.Sprintf(`by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
if got := r.Header.Get("Forwarded"); got != want {
t.Errorf("Forwarded = %v; want %v", got, want)
}

View File

@ -1596,16 +1596,13 @@ HTTP:
consists of character set [A-Za-z0-9._-], as described
in RFC 7239.
Default: obfuscated
--forwarded-for=(obfuscated|ip|<VALUE>)
--forwarded-for=(obfuscated|ip)
Specify the parameter value sent out with "for"
parameter of Forwarded header field. If "obfuscated" is
given, the string is randomly generated for each client
connection. If "ip" is given, the remote client address
of the connection, without port number, is sent with
"for" parameter. User can also specify the static
obfuscated string. The limitation is that it must start
with "_", and only consists of character set
[A-Za-z0-9._-], as described in RFC 7239.
"for" parameter.
Default: obfuscated
--no-via Don't append to Via header field. If Via header field
is received, it is left unaltered.

View File

@ -408,13 +408,9 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
if ((fwdconf.params & FORWARDED_FOR) &&
fwdconf.for_node_type == FORWARDED_NODE_OBFUSCATED) {
if (fwdconf.for_obfuscated.empty()) {
forwarded_for_obfuscated_ = "_";
forwarded_for_obfuscated_ += util::random_alpha_digit(
worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH);
} else {
forwarded_for_obfuscated_ = fwdconf.for_obfuscated;
}
forwarded_for_obfuscated_ = "_";
forwarded_for_obfuscated_ += util::random_alpha_digit(
worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH);
}
}

View File

@ -2123,7 +2123,8 @@ int parse_config(const char *opt, const char *optarg,
case SHRPX_OPTID_FORWARDED_FOR: {
auto type = parse_forwarded_node_type(optarg);
if (type == -1) {
if (type == -1 ||
(optid == SHRPX_OPTID_FORWARDED_FOR && optarg[0] == '_')) {
LOG(ERROR) << opt << ": unknown node type or illegal obfuscated string "
<< optarg;
return -1;
@ -2142,11 +2143,6 @@ int parse_config(const char *opt, const char *optarg,
break;
case SHRPX_OPTID_FORWARDED_FOR:
fwdconf.for_node_type = static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') {
fwdconf.for_obfuscated = optarg;
} else {
fwdconf.for_obfuscated = "";
}
break;
}

View File

@ -379,12 +379,9 @@ struct TLSConfig {
struct HttpConfig {
struct {
// obfuscated value used in "by" parameter of Forwarded header
// field.
std::string 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 for_obfuscated;
std::string by_obfuscated;
// bitwise-OR of one or more of shrpx_forwarded_param values.
uint32_t params;
// type of value recorded in "by" parameter of Forwarded header