Skip to content

Commit de3b7de

Browse files
m11yagentzh
authored andcommitted
feature: added pure C API for fetching client address in the SSL handshake phase.
Signed-off-by: Yichun Zhang (agentzh) <agentzh@gmail.com>
1 parent 4577a6f commit de3b7de

File tree

2 files changed

+272
-1
lines changed

2 files changed

+272
-1
lines changed

src/ngx_http_lua_ssl_certby.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,74 @@ ngx_http_lua_ffi_ssl_server_name(ngx_http_request_t *r, char **name,
884884
}
885885

886886

887+
int
888+
ngx_http_lua_ffi_ssl_raw_client_addr(ngx_http_request_t *r, char **addr,
889+
size_t *addrlen, int *addrtype, char **err)
890+
{
891+
#if (NGX_HAVE_UNIX_DOMAIN)
892+
struct sockaddr_un *saun;
893+
#endif
894+
ngx_ssl_conn_t *ssl_conn;
895+
ngx_connection_t *c;
896+
struct sockaddr_in *sin;
897+
#if (NGX_HAVE_INET6)
898+
struct sockaddr_in6 *sin6;
899+
#endif
900+
901+
if (r->connection == NULL || r->connection->ssl == NULL) {
902+
*err = "bad request";
903+
return NGX_ERROR;
904+
}
905+
906+
ssl_conn = r->connection->ssl->connection;
907+
if (ssl_conn == NULL) {
908+
*err = "bad ssl conn";
909+
return NGX_ERROR;
910+
}
911+
912+
c = ngx_ssl_get_connection(ssl_conn);
913+
914+
switch (c->sockaddr->sa_family) {
915+
916+
#if (NGX_HAVE_INET6)
917+
case AF_INET6:
918+
sin6 = (struct sockaddr_in6 *) c->sockaddr;
919+
*addrlen = 16;
920+
*addr = (char *) &sin6->sin6_addr.s6_addr;
921+
*addrtype = NGX_HTTP_LUA_ADDR_TYPE_INET6;
922+
923+
break;
924+
#endif
925+
926+
# if (NGX_HAVE_UNIX_DOMAIN)
927+
case AF_UNIX:
928+
saun = (struct sockaddr_un *)c->sockaddr;
929+
/* on Linux sockaddr might not include sun_path at all */
930+
if (c->socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
931+
*addr = "";
932+
*addrlen = 0;
933+
934+
} else {
935+
*addr = saun->sun_path;
936+
*addrlen = ngx_strlen(saun->sun_path);
937+
}
938+
939+
*addrtype = NGX_HTTP_LUA_ADDR_TYPE_UNIX;
940+
break;
941+
#endif
942+
943+
default: /* AF_INET */
944+
sin = (struct sockaddr_in *) c->sockaddr;
945+
*addr = (char *) &sin->sin_addr.s_addr;
946+
*addrlen = 4;
947+
*addrtype = NGX_HTTP_LUA_ADDR_TYPE_INET;
948+
break;
949+
}
950+
951+
return NGX_OK;
952+
}
953+
954+
887955
int
888956
ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der,
889957
char **err)

t/139-ssl-cert-by.t

Lines changed: 204 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ my $openssl_version = eval { `$NginxBinary -V 2>&1` };
1111
if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) {
1212
plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1");
1313
} else {
14-
plan tests => repeat_each() * (blocks() * 6 + 6);
14+
plan tests => repeat_each() * (blocks() * 6 + 4);
1515
}
1616

1717
$ENV{TEST_NGINX_HTML_DIR} ||= html_dir();
@@ -1872,3 +1872,206 @@ failed to do SSL handshake: handshake failed
18721872
qr/\[alert\] .*? no ssl_certificate_by_lua\* defined in server ~test2\\\.com\b/,
18731873
qr/\[crit\] .*? SSL_do_handshake\(\) failed\b/,
18741874
]
1875+
1876+
1877+
1878+
=== TEST 22: get raw_client_addr - IPv4
1879+
--- http_config
1880+
lua_package_path "../lua-resty-core/lib/?.lua;;";
1881+
1882+
server {
1883+
listen 127.0.0.1:12345 ssl;
1884+
server_name test.com;
1885+
1886+
ssl_certificate_by_lua_block {
1887+
local ssl = require "ngx.ssl"
1888+
local byte = string.byte
1889+
local addr, addrtype, err = ssl.raw_client_addr()
1890+
local ip = string.format("%d.%d.%d.%d", byte(addr, 1), byte(addr, 2),
1891+
byte(addr, 3), byte(addr, 4))
1892+
print("client ip: ", ip)
1893+
}
1894+
ssl_certificate ../../cert/test.crt;
1895+
ssl_certificate_key ../../cert/test.key;
1896+
1897+
server_tokens off;
1898+
location /foo {
1899+
default_type 'text/plain';
1900+
content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) }
1901+
more_clear_headers Date;
1902+
}
1903+
}
1904+
--- config
1905+
server_tokens off;
1906+
lua_ssl_trusted_certificate ../../cert/test.crt;
1907+
1908+
location /t {
1909+
content_by_lua_block {
1910+
do
1911+
local sock = ngx.socket.tcp()
1912+
1913+
sock:settimeout(2000)
1914+
1915+
local ok, err = sock:connect("127.0.0.1", 12345)
1916+
if not ok then
1917+
ngx.say("failed to connect: ", err)
1918+
return
1919+
end
1920+
1921+
ngx.say("connected: ", ok)
1922+
1923+
local sess, err = sock:sslhandshake(nil, "test.com", true)
1924+
if not sess then
1925+
ngx.say("failed to do SSL handshake: ", err)
1926+
return
1927+
end
1928+
1929+
ngx.say("ssl handshake: ", type(sess))
1930+
1931+
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
1932+
local bytes, err = sock:send(req)
1933+
if not bytes then
1934+
ngx.say("failed to send http request: ", err)
1935+
return
1936+
end
1937+
1938+
ngx.say("sent http request: ", bytes, " bytes.")
1939+
1940+
while true do
1941+
local line, err = sock:receive()
1942+
if not line then
1943+
-- ngx.say("failed to receive response status line: ", err)
1944+
break
1945+
end
1946+
1947+
ngx.say("received: ", line)
1948+
end
1949+
1950+
local ok, err = sock:close()
1951+
ngx.say("close: ", ok, " ", err)
1952+
end -- do
1953+
-- collectgarbage()
1954+
}
1955+
}
1956+
1957+
--- request
1958+
GET /t
1959+
--- response_body
1960+
connected: 1
1961+
ssl handshake: userdata
1962+
sent http request: 56 bytes.
1963+
received: HTTP/1.1 201 Created
1964+
received: Server: nginx
1965+
received: Content-Type: text/plain
1966+
received: Content-Length: 4
1967+
received: Connection: close
1968+
received:
1969+
received: foo
1970+
close: 1 nil
1971+
1972+
--- error_log
1973+
client ip: 127.0.0.1
1974+
1975+
--- no_error_log
1976+
[error]
1977+
[alert]
1978+
1979+
1980+
1981+
=== TEST 23: get raw_client_addr - unix domain socket
1982+
--- http_config
1983+
lua_package_path "../lua-resty-core/lib/?.lua;;";
1984+
1985+
server {
1986+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
1987+
server_name test.com;
1988+
1989+
ssl_certificate_by_lua_block {
1990+
local ssl = require "ngx.ssl"
1991+
local addr, addrtyp, err = ssl.raw_client_addr()
1992+
print("client socket file: ", addr)
1993+
}
1994+
ssl_certificate ../../cert/test.crt;
1995+
ssl_certificate_key ../../cert/test.key;
1996+
1997+
server_tokens off;
1998+
location /foo {
1999+
default_type 'text/plain';
2000+
content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) }
2001+
more_clear_headers Date;
2002+
}
2003+
}
2004+
--- config
2005+
server_tokens off;
2006+
lua_ssl_trusted_certificate ../../cert/test.crt;
2007+
2008+
location /t {
2009+
content_by_lua_block {
2010+
do
2011+
local sock = ngx.socket.tcp()
2012+
2013+
sock:settimeout(2000)
2014+
2015+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
2016+
if not ok then
2017+
ngx.say("failed to connect: ", err)
2018+
return
2019+
end
2020+
2021+
ngx.say("connected: ", ok)
2022+
2023+
local sess, err = sock:sslhandshake(nil, "test.com", true)
2024+
if not sess then
2025+
ngx.say("failed to do SSL handshake: ", err)
2026+
return
2027+
end
2028+
2029+
ngx.say("ssl handshake: ", type(sess))
2030+
2031+
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
2032+
local bytes, err = sock:send(req)
2033+
if not bytes then
2034+
ngx.say("failed to send http request: ", err)
2035+
return
2036+
end
2037+
2038+
ngx.say("sent http request: ", bytes, " bytes.")
2039+
2040+
while true do
2041+
local line, err = sock:receive()
2042+
if not line then
2043+
-- ngx.say("failed to receive response status line: ", err)
2044+
break
2045+
end
2046+
2047+
ngx.say("received: ", line)
2048+
end
2049+
2050+
local ok, err = sock:close()
2051+
ngx.say("close: ", ok, " ", err)
2052+
end -- do
2053+
-- collectgarbage()
2054+
}
2055+
}
2056+
2057+
--- request
2058+
GET /t
2059+
--- response_body
2060+
connected: 1
2061+
ssl handshake: userdata
2062+
sent http request: 56 bytes.
2063+
received: HTTP/1.1 201 Created
2064+
received: Server: nginx
2065+
received: Content-Type: text/plain
2066+
received: Content-Length: 4
2067+
received: Connection: close
2068+
received:
2069+
received: foo
2070+
close: 1 nil
2071+
2072+
--- error_log
2073+
client socket file:
2074+
2075+
--- no_error_log
2076+
[error]
2077+
[alert]

0 commit comments

Comments
 (0)