Skip to content

Commit fbdf655

Browse files
committed
Fix %<chi> with PROXY Protocol
1 parent 9484df9 commit fbdf655

File tree

9 files changed

+75
-16
lines changed

9 files changed

+75
-16
lines changed

iocore/net/P_NetVConnection.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ inline sockaddr const *
2828
NetVConnection::get_remote_addr()
2929
{
3030
if (!got_remote_addr) {
31-
if (pp_info.version != ProxyProtocolVersion::UNDEFINED) {
32-
set_remote_addr(get_proxy_protocol_src_addr());
33-
} else {
34-
set_remote_addr();
35-
}
31+
set_remote_addr();
3632
got_remote_addr = true;
3733
}
3834
return &remote_addr.sa;

iocore/net/SSLNetVConnection.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,7 @@ SSLNetVConnection::read_raw_data()
439439
// what we want now.
440440
void *payload = nullptr;
441441
if (!pp_ipmap->contains(get_remote_addr(), &payload)) {
442-
Debug("proxyprotocol", "proxy protocol src IP is NOT in the configured allowlist of trusted IPs - "
443-
"closing connection");
442+
Debug("proxyprotocol", "Source IP is NOT in the configured allowlist of trusted IPs - closing connection");
444443
r = -ENOTCONN; // Need a quick close/exit here to refuse the connection!!!!!!!!!
445444
goto proxy_protocol_bypass;
446445
} else {
@@ -455,7 +454,6 @@ SSLNetVConnection::read_raw_data()
455454

456455
if (this->has_proxy_protocol(buffer, &r)) {
457456
Debug("proxyprotocol", "ssl has proxy protocol header");
458-
set_remote_addr(get_proxy_protocol_src_addr());
459457
if (is_debug_tag_set("proxyprotocol")) {
460458
IpEndpoint dst;
461459
dst.sa = *(this->get_proxy_protocol_dst_addr());

proxy/ProtocolProbeSessionAccept.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessio
108108
void *payload = nullptr;
109109
if (!pp_ipmap->contains(netvc->get_remote_addr(), &payload)) {
110110
Debug("proxyprotocol",
111-
"ioCompletionEvent: proxy protocol src IP is NOT in the configured allowlist of trusted IPs - closing connection");
111+
"ioCompletionEvent: Source IP is NOT in the configured allowlist of trusted IPs - closing connection");
112112
goto done;
113113
} else {
114114
char new_host[INET6_ADDRSTRLEN];
@@ -123,7 +123,6 @@ struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessio
123123

124124
if (netvc->has_proxy_protocol(reader)) {
125125
Debug("proxyprotocol", "ioCompletionEvent: http has proxy protocol header");
126-
netvc->set_remote_addr(netvc->get_proxy_protocol_src_addr());
127126
} else {
128127
Debug("proxyprotocol",
129128
"ioCompletionEvent: proxy protocol was enabled, but required header was not present in the transaction - "

proxy/http/HttpTransactHeaders.cc

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -960,18 +960,27 @@ HttpTransactHeaders::add_forwarded_field_to_request(HttpTransact::State *s, HTTP
960960

961961
ts::LocalBufferWriter<1024> hdr;
962962

963-
if (optSet[HttpForwarded::FOR] and ats_is_ip(&s->client_info.src_addr.sa)) {
963+
IpEndpoint src_addr = s->client_info.src_addr;
964+
if (s->state_machine->ua_txn && s->state_machine->ua_txn->get_netvc()) {
965+
const ProxyProtocol &pp = s->state_machine->ua_txn->get_netvc()->get_proxy_protocol_info();
966+
967+
if (pp.version != ProxyProtocolVersion::UNDEFINED) {
968+
src_addr = pp.src_addr;
969+
}
970+
}
971+
972+
if (optSet[HttpForwarded::FOR] and ats_is_ip(&src_addr.sa)) {
964973
// NOTE: The logic within this if statement assumes that hdr is empty at this point.
965974

966975
hdr << "for=";
967976

968-
bool is_ipv6 = ats_is_ip6(&s->client_info.src_addr.sa);
977+
bool is_ipv6 = ats_is_ip6(&src_addr.sa);
969978

970979
if (is_ipv6) {
971980
hdr << "\"[";
972981
}
973982

974-
if (ats_ip_ntop(&s->client_info.src_addr.sa, hdr.auxBuffer(), hdr.remaining()) == nullptr) {
983+
if (ats_ip_ntop(&src_addr.sa, hdr.auxBuffer(), hdr.remaining()) == nullptr) {
975984
Debug("http_trans", "[add_forwarded_field_to_outgoing_request] ats_ip_ntop() call failed");
976985
return;
977986
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
127.0.0.1 127.0.0.1
2+
127.0.0.1 127.0.0.1
3+
127.0.0.1 198.51.100.1

tests/gold_tests/proxy_protocol/gold/test_case_0_stdout.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
``
33
"headers": {
44
``
5-
"Forwarded": "for=127.0.0.1;proto=http",
5+
"Forwarded": "for=127.0.0.1;by=127.0.0.1;proto=http",
66
``
77
},
88
``

tests/gold_tests/proxy_protocol/gold/test_case_1_stdout.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
``
33
"headers": {
44
``
5-
"Forwarded": "for=127.0.0.1;proto=https",
5+
"Forwarded": "for=127.0.0.1;by=127.0.0.1;proto=https",
66
``
77
},
88
``
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
HTTP/1.1 200 OK
2+
Server: ATS/``
3+
Date: ``
4+
Age: ``
5+
6+
{
7+
``
8+
"headers":``{
9+
``
10+
"Forwarded":``"for=198.51.100.1;by=127.0.0.1;proto=http",
11+
``
12+
},
13+
``
14+
}

tests/gold_tests/proxy_protocol/proxy_protocol.test.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# See the License for the specific language governing permissions and
1717
# limitations under the License.
1818

19+
import os
1920
import sys
2021

2122
Test.Summary = 'Test PROXY Protocol'
@@ -49,13 +50,25 @@ def setupTS(self):
4950
self.ts.Disk.records_config.update({
5051
"proxy.config.http.server_ports": f"{self.ts.Variables.port}:pp {self.ts.Variables.ssl_port}:ssl:pp",
5152
"proxy.config.http.proxy_protocol_allowlist": "127.0.0.1",
52-
"proxy.config.http.insert_forwarded": "for|proto",
53+
"proxy.config.http.insert_forwarded": "for|by=ip|proto",
5354
"proxy.config.ssl.server.cert.path": f"{self.ts.Variables.SSLDir}",
5455
"proxy.config.ssl.server.private_key.path": f"{self.ts.Variables.SSLDir}",
5556
"proxy.config.diags.debug.enabled": 1,
5657
"proxy.config.diags.debug.tags": "proxyprotocol",
5758
})
5859

60+
self.ts.Disk.logging_yaml.AddLines(
61+
'''
62+
logging:
63+
formats:
64+
- name: access
65+
format: '%<chi> %<pps>'
66+
67+
logs:
68+
- filename: access
69+
format: access
70+
'''.split("\n"))
71+
5972
def addTestCase0(self):
6073
"""
6174
Incoming PROXY Protocol v1 on TCP port
@@ -82,9 +95,36 @@ def addTestCase1(self):
8295
tr.StillRunningAfter = self.httpbin
8396
tr.StillRunningAfter = self.ts
8497

98+
def addTestCase2(self):
99+
"""
100+
Test with netcat
101+
"""
102+
tr = Test.AddTestRun()
103+
tr.Processes.Default.Command = f"echo 'PROXY TCP4 198.51.100.1 198.51.100.2 51137 80\r\nGET /get HTTP/1.1\r\nHost: 127.0.0.1:80\r\n' | nc localhost {self.ts.Variables.port}"
104+
tr.Processes.Default.ReturnCode = 0
105+
tr.Processes.Default.Streams.stdout = "gold/test_case_2_stdout.gold"
106+
tr.StillRunningAfter = self.httpbin
107+
tr.StillRunningAfter = self.ts
108+
109+
def addTestCase99(self):
110+
"""
111+
check access log
112+
"""
113+
Test.Disk.File(os.path.join(self.ts.Variables.LOGDIR, 'access.log'), exists=True, content='gold/access.gold')
114+
115+
# Wait for log file to appear, then wait one extra second to make sure TS is done writing it.
116+
tr = Test.AddTestRun()
117+
tr.Processes.Default.Command = (
118+
os.path.join(Test.Variables.AtsTestToolsDir, 'condwait') + ' 60 1 -f ' +
119+
os.path.join(self.ts.Variables.LOGDIR, 'access.log')
120+
)
121+
tr.Processes.Default.ReturnCode = 0
122+
85123
def run(self):
86124
self.addTestCase0()
87125
self.addTestCase1()
126+
self.addTestCase2()
127+
self.addTestCase99()
88128

89129

90130
ProxyProtocolTest().run()

0 commit comments

Comments
 (0)