Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
ce53bd23
Commit
ce53bd23
authored
Sep 06, 2015
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nghttpx: Implement PROXY protocol version 1
Use --accept-proxy-protocol to enable PROXY protocol handling
parent
39287314
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
220 additions
and
1 deletion
+220
-1
gennghttpxfun.py
gennghttpxfun.py
+1
-0
src/shrpx.cc
src/shrpx.cc
+5
-0
src/shrpx_client_handler.cc
src/shrpx_client_handler.cc
+191
-0
src/shrpx_client_handler.h
src/shrpx_client_handler.h
+4
-0
src/shrpx_config.cc
src/shrpx_config.cc
+10
-0
src/shrpx_config.h
src/shrpx_config.h
+2
-0
src/util.cc
src/util.cc
+5
-1
src/util.h
src/util.h
+2
-0
No files found.
gennghttpxfun.py
View file @
ce53bd23
...
...
@@ -100,6 +100,7 @@ OPTIONS = [
"tls-ticket-key-memcached-max-fail"
,
"request-phase-file"
,
"response-phase-file"
,
"accept-proxy-protocol"
,
"conf"
,
]
...
...
src/shrpx.cc
View file @
ce53bd23
...
...
@@ -1915,6 +1915,7 @@ int main(int argc, char **argv) {
90
},
{
SHRPX_OPT_REQUEST_PHASE_FILE
,
required_argument
,
&
flag
,
91
},
{
SHRPX_OPT_RESPONSE_PHASE_FILE
,
required_argument
,
&
flag
,
92
},
{
SHRPX_OPT_ACCEPT_PROXY_PROTOCOL
,
no_argument
,
&
flag
,
93
},
{
nullptr
,
0
,
nullptr
,
0
}};
int
option_index
=
0
;
...
...
@@ -2316,6 +2317,10 @@ int main(int argc, char **argv) {
// --response-phase-file
cmdcfgs
.
emplace_back
(
SHRPX_OPT_RESPONSE_PHASE_FILE
,
optarg
);
break
;
case
93
:
// --accept-proxy-protocol
cmdcfgs
.
emplace_back
(
SHRPX_OPT_ACCEPT_PROXY_PROTOCOL
,
"yes"
);
break
;
default:
break
;
}
...
...
src/shrpx_client_handler.cc
View file @
ce53bd23
...
...
@@ -382,6 +382,16 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
conn_
.
rlimit
.
startw
();
ev_timer_again
(
conn_
.
loop
,
&
conn_
.
rt
);
if
(
get_config
()
->
accept_proxy_protocol
)
{
read_
=
write_
=
&
ClientHandler
::
read_clear
;
on_read_
=
&
ClientHandler
::
proxy_protocol_read
;
on_write_
=
&
ClientHandler
::
upstream_noop
;
}
else
{
setup_upstream_io_callback
();
}
}
void
ClientHandler
::
setup_upstream_io_callback
()
{
if
(
conn_
.
tls
.
ssl
)
{
conn_
.
prepare_server_handshake
();
read_
=
write_
=
&
ClientHandler
::
tls_handshake
;
...
...
@@ -829,4 +839,185 @@ ev_io *ClientHandler::get_wev() { return &conn_.wev; }
Worker
*
ClientHandler
::
get_worker
()
const
{
return
worker_
;
}
namespace
{
ssize_t
parse_proxy_line_port
(
const
uint8_t
*
first
,
const
uint8_t
*
last
)
{
auto
p
=
first
;
int32_t
port
=
0
;
for
(;
p
!=
last
&&
util
::
isDigit
(
*
p
);
++
p
)
{
port
*=
10
;
port
+=
*
p
-
'0'
;
if
(
port
>
65535
)
{
return
-
1
;
}
}
return
p
-
first
;
}
}
// namespace
int
ClientHandler
::
proxy_protocol_read
()
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol: Started"
;
}
auto
first
=
rb_
.
pos
;
// NULL character really destroys getaddrinfo function. We won't
// expect it in PROXY protocol line, so find it here.
auto
chrs
=
std
::
array
<
char
,
2
>
{{
'\r'
,
'\0'
}};
auto
end
=
std
::
find_first_of
(
rb_
.
pos
,
rb_
.
pos
+
rb_
.
rleft
(),
std
::
begin
(
chrs
),
std
::
end
(
chrs
));
if
(
end
+
2
>
rb_
.
pos
+
rb_
.
rleft
()
||
*
end
==
'\0'
||
end
[
1
]
!=
'\n'
)
{
return
-
1
;
}
constexpr
const
char
HEADER
[]
=
"PROXY "
;
if
(
rb_
.
rleft
()
<
str_size
(
HEADER
))
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: PROXY version 1 ID not found"
;
}
return
-
1
;
}
if
(
!
util
::
streq_l
(
HEADER
,
rb_
.
pos
,
str_size
(
HEADER
)))
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Bad PROXY protocol version 1 ID"
;
}
return
-
1
;
}
rb_
.
drain
(
str_size
(
HEADER
));
int
family
;
if
(
rb_
.
pos
[
0
]
==
'T'
)
{
if
(
rb_
.
rleft
()
<
5
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: INET protocol family not found"
;
}
return
-
1
;
}
if
(
util
::
streq_l
(
"TCP4 "
,
rb_
.
pos
,
5
))
{
family
=
AF_INET
;
}
else
if
(
util
::
streq_l
(
"TCP6 "
,
rb_
.
pos
,
5
))
{
family
=
AF_INET6
;
}
else
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Unknown INET protocol family"
;
}
return
-
1
;
}
rb_
.
drain
(
5
);
}
else
{
if
(
rb_
.
rleft
()
<
7
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: INET protocol family not found"
;
}
return
-
1
;
}
if
(
!
util
::
streq_l
(
"UNKNOWN"
,
rb_
.
pos
,
7
))
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Unknown INET protocol family"
;
}
return
-
1
;
}
return
0
;
}
// source address
auto
token_end
=
std
::
find
(
rb_
.
pos
,
end
,
' '
);
if
(
token_end
==
end
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Source address not found"
;
}
return
-
1
;
}
*
token_end
=
'\0'
;
if
(
!
util
::
numeric_host
(
reinterpret_cast
<
const
char
*>
(
rb_
.
pos
),
family
))
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Invalid source address"
;
}
return
-
1
;
}
auto
src_addr
=
rb_
.
pos
;
auto
src_addrlen
=
token_end
-
rb_
.
pos
;
rb_
.
drain
(
token_end
-
rb_
.
pos
+
1
);
// destination address
token_end
=
std
::
find
(
rb_
.
pos
,
end
,
' '
);
if
(
token_end
==
end
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Destination address not found"
;
}
return
-
1
;
}
*
token_end
=
'\0'
;
if
(
!
util
::
numeric_host
(
reinterpret_cast
<
const
char
*>
(
rb_
.
pos
),
family
))
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Invalid destination address"
;
}
return
-
1
;
}
// Currently we don't use destination address
rb_
.
drain
(
token_end
-
rb_
.
pos
+
1
);
// source port
auto
n
=
parse_proxy_line_port
(
rb_
.
pos
,
end
);
if
(
n
<=
0
||
*
(
rb_
.
pos
+
n
)
!=
' '
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Invalid source port"
;
}
return
-
1
;
}
rb_
.
pos
[
n
]
=
'\0'
;
auto
src_port
=
rb_
.
pos
;
auto
src_portlen
=
n
;
rb_
.
drain
(
n
+
1
);
// destination port
n
=
parse_proxy_line_port
(
rb_
.
pos
,
end
);
if
(
n
<=
0
||
rb_
.
pos
+
n
!=
end
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Invalid destination port"
;
}
return
-
1
;
}
// Currently we don't use destination port
rb_
.
drain
(
end
+
2
-
rb_
.
pos
);
ipaddr_
.
assign
(
src_addr
,
src_addr
+
src_addrlen
);
port_
.
assign
(
src_port
,
src_port
+
src_portlen
);
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Finished, "
<<
(
rb_
.
pos
-
first
)
<<
" bytes read"
;
}
setup_upstream_io_callback
();
// Run on_read to process data left in buffer since they are not
// notified further
if
(
on_read
()
!=
0
)
{
return
-
1
;
}
return
0
;
}
}
// namespace shrpx
src/shrpx_client_handler.h
View file @
ce53bd23
...
...
@@ -71,6 +71,8 @@ public:
int
upstream_http1_connhd_read
();
int
upstream_write
();
int
proxy_protocol_read
();
// Performs I/O operation. Internally calls on_read()/on_write().
int
do_read
();
int
do_write
();
...
...
@@ -130,6 +132,8 @@ public:
void
signal_write
();
ev_io
*
get_wev
();
void
setup_upstream_io_callback
();
private:
Connection
conn_
;
ev_timer
reneg_shutdown_timer_
;
...
...
src/shrpx_config.cc
View file @
ce53bd23
...
...
@@ -625,6 +625,7 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
// generated by gennghttpxfun.py
enum
{
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL
,
SHRPX_OPTID_ACCESSLOG_FILE
,
SHRPX_OPTID_ACCESSLOG_FORMAT
,
SHRPX_OPTID_ACCESSLOG_SYSLOG
,
...
...
@@ -1099,6 +1100,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return
SHRPX_OPTID_BACKEND_TLS_SNI_FIELD
;
}
break
;
case
'l'
:
if
(
util
::
strieq_l
(
"accept-proxy-protoco"
,
name
,
20
))
{
return
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL
;
}
break
;
case
'r'
:
if
(
util
::
strieq_l
(
"tls-ticket-key-ciphe"
,
name
,
20
))
{
return
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER
;
...
...
@@ -1968,6 +1974,10 @@ int parse_config(const char *opt, const char *optarg,
LOG
(
WARN
)
<<
opt
<<
": ignored because mruby support is disabled at build time."
;
#endif // !HAVE_MRUBY
return
0
;
case
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL
:
mod_config
()
->
accept_proxy_protocol
=
util
::
strieq
(
optarg
,
"yes"
);
return
0
;
case
SHRPX_OPTID_CONF
:
LOG
(
WARN
)
<<
"conf: ignored"
;
...
...
src/shrpx_config.h
View file @
ce53bd23
...
...
@@ -185,6 +185,7 @@ constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] =
"tls-ticket-key-memcached-max-fail"
;
constexpr
char
SHRPX_OPT_REQUEST_PHASE_FILE
[]
=
"request-phase-file"
;
constexpr
char
SHRPX_OPT_RESPONSE_PHASE_FILE
[]
=
"response-phase-file"
;
constexpr
char
SHRPX_OPT_ACCEPT_PROXY_PROTOCOL
[]
=
"accept-proxy-protocol"
;
union
sockaddr_union
{
sockaddr_storage
storage
;
...
...
@@ -409,6 +410,7 @@ struct Config {
bool
no_ocsp
;
// true if --tls-ticket-key-cipher is used
bool
tls_ticket_key_cipher_given
;
bool
accept_proxy_protocol
;
};
const
Config
*
get_config
();
...
...
src/util.cc
View file @
ce53bd23
...
...
@@ -636,9 +636,13 @@ void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
}
bool
numeric_host
(
const
char
*
hostname
)
{
return
numeric_host
(
hostname
,
AF_UNSPEC
);
}
bool
numeric_host
(
const
char
*
hostname
,
int
family
)
{
struct
addrinfo
*
res
;
struct
addrinfo
hints
{};
hints
.
ai_family
=
AF_UNSPEC
;
hints
.
ai_family
=
family
;
hints
.
ai_flags
=
AI_NUMERICHOST
;
if
(
getaddrinfo
(
hostname
,
nullptr
,
&
hints
,
&
res
))
{
return
false
;
...
...
src/util.h
View file @
ce53bd23
...
...
@@ -512,6 +512,8 @@ void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
bool
numeric_host
(
const
char
*
hostname
);
bool
numeric_host
(
const
char
*
hostname
,
int
family
);
// Returns numeric address string of |addr|. If getnameinfo() is
// failed, "unknown" is returned.
std
::
string
numeric_name
(
const
struct
sockaddr
*
sa
,
socklen_t
salen
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment