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
7d481db2
Commit
7d481db2
authored
Sep 07, 2015
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'nghttpx-proxyprotocol'
parents
4f52f60b
026ab797
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
638 additions
and
9 deletions
+638
-9
gennghttpxfun.py
gennghttpxfun.py
+1
-0
integration-tests/nghttpx_http2_test.go
integration-tests/nghttpx_http2_test.go
+356
-0
src/shrpx.cc
src/shrpx.cc
+7
-0
src/shrpx_client_handler.cc
src/shrpx_client_handler.cc
+244
-0
src/shrpx_client_handler.h
src/shrpx_client_handler.h
+6
-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
+10
-9
src/util.h
src/util.h
+2
-0
No files found.
gennghttpxfun.py
View file @
7d481db2
...
@@ -100,6 +100,7 @@ OPTIONS = [
...
@@ -100,6 +100,7 @@ OPTIONS = [
"tls-ticket-key-memcached-max-fail"
,
"tls-ticket-key-memcached-max-fail"
,
"request-phase-file"
,
"request-phase-file"
,
"response-phase-file"
,
"response-phase-file"
,
"accept-proxy-protocol"
,
"conf"
,
"conf"
,
]
]
...
...
integration-tests/nghttpx_http2_test.go
View file @
7d481db2
This diff is collapsed.
Click to expand it.
src/shrpx.cc
View file @
7d481db2
...
@@ -1268,6 +1268,8 @@ Connections:
...
@@ -1268,6 +1268,8 @@ Connections:
timeouts when connecting and making CONNECT request can
timeouts when connecting and making CONNECT request can
be specified by --backend-read-timeout and
be specified by --backend-read-timeout and
--backend-write-timeout options.
--backend-write-timeout options.
--accept-proxy-protocol
Accept PROXY protocol version 1 on frontend connection.
Performance:
Performance:
-n, --workers=<N>
-n, --workers=<N>
...
@@ -1915,6 +1917,7 @@ int main(int argc, char **argv) {
...
@@ -1915,6 +1917,7 @@ int main(int argc, char **argv) {
90
},
90
},
{
SHRPX_OPT_REQUEST_PHASE_FILE
,
required_argument
,
&
flag
,
91
},
{
SHRPX_OPT_REQUEST_PHASE_FILE
,
required_argument
,
&
flag
,
91
},
{
SHRPX_OPT_RESPONSE_PHASE_FILE
,
required_argument
,
&
flag
,
92
},
{
SHRPX_OPT_RESPONSE_PHASE_FILE
,
required_argument
,
&
flag
,
92
},
{
SHRPX_OPT_ACCEPT_PROXY_PROTOCOL
,
no_argument
,
&
flag
,
93
},
{
nullptr
,
0
,
nullptr
,
0
}};
{
nullptr
,
0
,
nullptr
,
0
}};
int
option_index
=
0
;
int
option_index
=
0
;
...
@@ -2316,6 +2319,10 @@ int main(int argc, char **argv) {
...
@@ -2316,6 +2319,10 @@ int main(int argc, char **argv) {
// --response-phase-file
// --response-phase-file
cmdcfgs
.
emplace_back
(
SHRPX_OPT_RESPONSE_PHASE_FILE
,
optarg
);
cmdcfgs
.
emplace_back
(
SHRPX_OPT_RESPONSE_PHASE_FILE
,
optarg
);
break
;
break
;
case
93
:
// --accept-proxy-protocol
cmdcfgs
.
emplace_back
(
SHRPX_OPT_ACCEPT_PROXY_PROTOCOL
,
"yes"
);
break
;
default:
default:
break
;
break
;
}
}
...
...
src/shrpx_client_handler.cc
View file @
7d481db2
...
@@ -104,6 +104,8 @@ void writecb(struct ev_loop *loop, ev_io *w, int revents) {
...
@@ -104,6 +104,8 @@ void writecb(struct ev_loop *loop, ev_io *w, int revents) {
}
}
}
// namespace
}
// namespace
int
ClientHandler
::
noop
()
{
return
0
;
}
int
ClientHandler
::
read_clear
()
{
int
ClientHandler
::
read_clear
()
{
ev_timer_again
(
conn_
.
loop
,
&
conn_
.
rt
);
ev_timer_again
(
conn_
.
loop
,
&
conn_
.
rt
);
...
@@ -382,6 +384,17 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
...
@@ -382,6 +384,17 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
conn_
.
rlimit
.
startw
();
conn_
.
rlimit
.
startw
();
ev_timer_again
(
conn_
.
loop
,
&
conn_
.
rt
);
ev_timer_again
(
conn_
.
loop
,
&
conn_
.
rt
);
if
(
get_config
()
->
accept_proxy_protocol
)
{
read_
=
&
ClientHandler
::
read_clear
;
write_
=
&
ClientHandler
::
noop
;
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
)
{
if
(
conn_
.
tls
.
ssl
)
{
conn_
.
prepare_server_handshake
();
conn_
.
prepare_server_handshake
();
read_
=
write_
=
&
ClientHandler
::
tls_handshake
;
read_
=
write_
=
&
ClientHandler
::
tls_handshake
;
...
@@ -829,4 +842,235 @@ ev_io *ClientHandler::get_wev() { return &conn_.wev; }
...
@@ -829,4 +842,235 @@ ev_io *ClientHandler::get_wev() { return &conn_.wev; }
Worker
*
ClientHandler
::
get_worker
()
const
{
return
worker_
;
}
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
;
if
(
p
==
last
)
{
return
-
1
;
}
if
(
*
p
==
'0'
)
{
if
(
p
+
1
!=
last
&&
util
::
isDigit
(
*
(
p
+
1
)))
{
return
-
1
;
}
return
1
;
}
for
(;
p
!=
last
&&
util
::
isDigit
(
*
p
);
++
p
)
{
port
*=
10
;
port
+=
*
p
-
'0'
;
if
(
port
>
65535
)
{
return
-
1
;
}
}
return
p
-
first
;
}
}
// namespace
int
ClientHandler
::
on_proxy_protocol_finish
()
{
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
;
}
// http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
int
ClientHandler
::
proxy_protocol_read
()
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol: Started"
;
}
auto
first
=
rb_
.
pos
;
// NULL character really destroys functions which expects NULL
// terminated string. We won't expect it in PROXY protocol line, so
// find it here.
auto
chrs
=
std
::
array
<
char
,
2
>
{{
'\n'
,
'\0'
}};
constexpr
size_t
MAX_PROXY_LINELEN
=
107
;
auto
bufend
=
rb_
.
pos
+
std
::
min
(
MAX_PROXY_LINELEN
,
rb_
.
rleft
());
auto
end
=
std
::
find_first_of
(
rb_
.
pos
,
bufend
,
std
::
begin
(
chrs
),
std
::
end
(
chrs
));
if
(
end
==
bufend
)
{
if
(
rb_
.
rleft
()
>=
MAX_PROXY_LINELEN
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: No ending CR LF sequence found"
;
}
return
-
1
;
}
return
0
;
}
if
(
*
end
==
'\0'
||
end
==
rb_
.
pos
||
*
(
end
-
1
)
!=
'\r'
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: No ending CR LF sequence found"
;
}
return
-
1
;
}
--
end
;
constexpr
const
char
HEADER
[]
=
"PROXY "
;
if
(
end
-
rb_
.
pos
<
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
(
end
-
rb_
.
pos
<
5
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: INET protocol family not found"
;
}
return
-
1
;
}
if
(
rb_
.
pos
[
1
]
!=
'C'
||
rb_
.
pos
[
2
]
!=
'P'
)
{
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Unknown INET protocol family"
;
}
return
-
1
;
}
switch
(
rb_
.
pos
[
3
])
{
case
'4'
:
family
=
AF_INET
;
break
;
case
'6'
:
family
=
AF_INET6
;
break
;
default:
if
(
LOG_ENABLED
(
INFO
))
{
CLOG
(
INFO
,
this
)
<<
"PROXY-protocol-v1: Unknown INET protocol family"
;
}
return
-
1
;
}
rb_
.
drain
(
5
);
}
else
{
if
(
end
-
rb_
.
pos
<
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
;
}
rb_
.
drain
(
end
+
2
-
rb_
.
pos
);
return
on_proxy_protocol_finish
();
}
// 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"
;
}
return
on_proxy_protocol_finish
();
}
}
// namespace shrpx
}
// namespace shrpx
src/shrpx_client_handler.h
View file @
7d481db2
...
@@ -56,6 +56,7 @@ public:
...
@@ -56,6 +56,7 @@ public:
const
char
*
port
);
const
char
*
port
);
~
ClientHandler
();
~
ClientHandler
();
int
noop
();
// Performs clear text I/O
// Performs clear text I/O
int
read_clear
();
int
read_clear
();
int
write_clear
();
int
write_clear
();
...
@@ -71,6 +72,9 @@ public:
...
@@ -71,6 +72,9 @@ public:
int
upstream_http1_connhd_read
();
int
upstream_http1_connhd_read
();
int
upstream_write
();
int
upstream_write
();
int
proxy_protocol_read
();
int
on_proxy_protocol_finish
();
// Performs I/O operation. Internally calls on_read()/on_write().
// Performs I/O operation. Internally calls on_read()/on_write().
int
do_read
();
int
do_read
();
int
do_write
();
int
do_write
();
...
@@ -130,6 +134,8 @@ public:
...
@@ -130,6 +134,8 @@ public:
void
signal_write
();
void
signal_write
();
ev_io
*
get_wev
();
ev_io
*
get_wev
();
void
setup_upstream_io_callback
();
private:
private:
Connection
conn_
;
Connection
conn_
;
ev_timer
reneg_shutdown_timer_
;
ev_timer
reneg_shutdown_timer_
;
...
...
src/shrpx_config.cc
View file @
7d481db2
...
@@ -625,6 +625,7 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
...
@@ -625,6 +625,7 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
// generated by gennghttpxfun.py
// generated by gennghttpxfun.py
enum
{
enum
{
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL
,
SHRPX_OPTID_ACCESSLOG_FILE
,
SHRPX_OPTID_ACCESSLOG_FILE
,
SHRPX_OPTID_ACCESSLOG_FORMAT
,
SHRPX_OPTID_ACCESSLOG_FORMAT
,
SHRPX_OPTID_ACCESSLOG_SYSLOG
,
SHRPX_OPTID_ACCESSLOG_SYSLOG
,
...
@@ -1099,6 +1100,11 @@ int option_lookup_token(const char *name, size_t namelen) {
...
@@ -1099,6 +1100,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return
SHRPX_OPTID_BACKEND_TLS_SNI_FIELD
;
return
SHRPX_OPTID_BACKEND_TLS_SNI_FIELD
;
}
}
break
;
break
;
case
'l'
:
if
(
util
::
strieq_l
(
"accept-proxy-protoco"
,
name
,
20
))
{
return
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL
;
}
break
;
case
'r'
:
case
'r'
:
if
(
util
::
strieq_l
(
"tls-ticket-key-ciphe"
,
name
,
20
))
{
if
(
util
::
strieq_l
(
"tls-ticket-key-ciphe"
,
name
,
20
))
{
return
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER
;
return
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER
;
...
@@ -1968,6 +1974,10 @@ int parse_config(const char *opt, const char *optarg,
...
@@ -1968,6 +1974,10 @@ int parse_config(const char *opt, const char *optarg,
LOG
(
WARN
)
<<
opt
LOG
(
WARN
)
<<
opt
<<
": ignored because mruby support is disabled at build time."
;
<<
": ignored because mruby support is disabled at build time."
;
#endif // !HAVE_MRUBY
#endif // !HAVE_MRUBY
return
0
;
case
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL
:
mod_config
()
->
accept_proxy_protocol
=
util
::
strieq
(
optarg
,
"yes"
);
return
0
;
return
0
;
case
SHRPX_OPTID_CONF
:
case
SHRPX_OPTID_CONF
:
LOG
(
WARN
)
<<
"conf: ignored"
;
LOG
(
WARN
)
<<
"conf: ignored"
;
...
...
src/shrpx_config.h
View file @
7d481db2
...
@@ -185,6 +185,7 @@ constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] =
...
@@ -185,6 +185,7 @@ constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] =
"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_REQUEST_PHASE_FILE
[]
=
"request-phase-file"
;
constexpr
char
SHRPX_OPT_RESPONSE_PHASE_FILE
[]
=
"response-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
{
union
sockaddr_union
{
sockaddr_storage
storage
;
sockaddr_storage
storage
;
...
@@ -409,6 +410,7 @@ struct Config {
...
@@ -409,6 +410,7 @@ struct Config {
bool
no_ocsp
;
bool
no_ocsp
;
// true if --tls-ticket-key-cipher is used
// true if --tls-ticket-key-cipher is used
bool
tls_ticket_key_cipher_given
;
bool
tls_ticket_key_cipher_given
;
bool
accept_proxy_protocol
;
};
};
const
Config
*
get_config
();
const
Config
*
get_config
();
...
...
src/util.cc
View file @
7d481db2
...
@@ -626,15 +626,16 @@ void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
...
@@ -626,15 +626,16 @@ 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
)
{
struct
addrinfo
*
res
;
return
numeric_host
(
hostname
,
AF_INET
)
||
numeric_host
(
hostname
,
AF_INET6
);
struct
addrinfo
hints
{};
}
hints
.
ai_family
=
AF_UNSPEC
;
hints
.
ai_flags
=
AI_NUMERICHOST
;
bool
numeric_host
(
const
char
*
hostname
,
int
family
)
{
if
(
getaddrinfo
(
hostname
,
nullptr
,
&
hints
,
&
res
))
{
int
rv
;
return
false
;
std
::
array
<
uint8_t
,
sizeof
(
struct
in6_addr
)
>
dst
;
}
freeaddrinfo
(
res
);
rv
=
inet_pton
(
family
,
hostname
,
dst
.
data
());
return
true
;
return
rv
==
1
;
}
}
std
::
string
numeric_name
(
const
struct
sockaddr
*
sa
,
socklen_t
salen
)
{
std
::
string
numeric_name
(
const
struct
sockaddr
*
sa
,
socklen_t
salen
)
{
...
...
src/util.h
View file @
7d481db2
...
@@ -516,6 +516,8 @@ void write_uri_field(std::ostream &o, const char *uri, const http_parser_url &u,
...
@@ -516,6 +516,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
);
bool
numeric_host
(
const
char
*
hostname
,
int
family
);
// Returns numeric address string of |addr|. If getnameinfo() is
// Returns numeric address string of |addr|. If getnameinfo() is
// failed, "unknown" is returned.
// failed, "unknown" is returned.
std
::
string
numeric_name
(
const
struct
sockaddr
*
sa
,
socklen_t
salen
);
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