aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-03-25 13:44:40 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-03-25 13:48:56 +0200
commite801d94e40f23c09f27a807fec48fc0133ddb1c6 (patch)
treea7cae42d7f81c4becddecdf69fc854a42e81e555
parenta6d6598a99f654cf25a65e512ce7bf4856fda3b2 (diff)
downloadvmod-remoteip-e801d94e40f23c09f27a807fec48fc0133ddb1c6.tar.gz
vmod-remoteip-e801d94e40f23c09f27a807fec48fc0133ddb1c6.tar.bz2
Use ACL to hold IPs of the trusted proxies.v2.0
Suggested by Dridi Boukelmoune.
-rw-r--r--NEWS9
-rw-r--r--README11
-rw-r--r--configure.ac2
-rw-r--r--src/vmod_remoteip.c313
-rw-r--r--src/vmod_remoteip.vcc34
-rw-r--r--tests/ipv4found.at8
-rw-r--r--tests/ipv4notfound.at8
-rw-r--r--tests/ipv6found.at8
-rw-r--r--tests/ipv6notfound.at8
9 files changed, 66 insertions, 335 deletions
diff --git a/NEWS b/NEWS
index 85185fc..aed17ee 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,15 @@
1vmod_remoteip -- history of user-visible changes. 2020-03-21 1vmod_remoteip -- history of user-visible changes. 2020-03-25
2See the end of file for copying conditions. 2See the end of file for copying conditions.
3 3
4Please send vmod_remoteip bug reports to <gray@gnu.org> 4Please send vmod_remoteip bug reports to <gray@gnu.org>
5 5
6Version 2.0, 2020-03-25
7
8* Use ACL to hold IPs of the trusted proxies.
9
10The ACL name is passed as the first argument to the remoteip.get
11function. The remoteip.init function is now gone.
12
6Version 1.0, 2020-03-21 13Version 1.0, 2020-03-21
7 14
8Initial release 15Initial release
diff --git a/README b/README
index ca814ba..d022c28 100644
--- a/README
+++ b/README
@@ -20,10 +20,11 @@ hosts from the ACL "allowed":
20#+BEGIN_SRC vcl-script 20#+BEGIN_SRC vcl-script
21 import std; 21 import std;
22 import remoteip; 22 import remoteip;
23 23
24 sub vcl_init { 24 // Register trusted proxy server addresses
25 // Register trusted proxy server addresses 25 acl trusted {
26 remoteip.init("192.0.2.1, 127.0.0.1"); 26 "192.0.2.1";
27 "127.0.0.1";
27 } 28 }
28 29
29 acl allowed { 30 acl allowed {
@@ -32,7 +33,7 @@ hosts from the ACL "allowed":
32 } 33 }
33 34
34 sub vcl_recv { 35 sub vcl_recv {
35 set req.http.x-real-ip = remoteip.get(req.http.X-Forwarded-For); 36 set req.http.x-real-ip = remoteip.get(trusted, req.http.X-Forwarded-For);
36 if (std.ip(req.http.x-real-ip) ~ allowed) { 37 if (std.ip(req.http.x-real-ip) ~ allowed) {
37 ... 38 ...
38 } 39 }
diff --git a/configure.ac b/configure.ac
index cc8480a..1fcc3bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,7 +15,7 @@
15# along with vmod_remoteip. If not, see <http://www.gnu.org/licenses/>. 15# along with vmod_remoteip. If not, see <http://www.gnu.org/licenses/>.
16 16
17AC_PREREQ(2.69) 17AC_PREREQ(2.69)
18AC_INIT([vmod-remoteip], [1.0], [gray@gnu.org]) 18AC_INIT([vmod-remoteip], [2.0], [gray@gnu.org])
19AC_CONFIG_AUX_DIR([build-aux]) 19AC_CONFIG_AUX_DIR([build-aux])
20AC_CONFIG_MACRO_DIR([m4]) 20AC_CONFIG_MACRO_DIR([m4])
21AC_CONFIG_SRCDIR(src/vmod_remoteip.vcc) 21AC_CONFIG_SRCDIR(src/vmod_remoteip.vcc)
diff --git a/src/vmod_remoteip.c b/src/vmod_remoteip.c
index 528b0a4..8bba147 100644
--- a/src/vmod_remoteip.c
+++ b/src/vmod_remoteip.c
@@ -26,314 +26,43 @@
26#include <cache/cache.h> 26#include <cache/cache.h>
27#include <vcl.h> 27#include <vcl.h>
28#include <vcc_if.h> 28#include <vcc_if.h>
29#include <vqueue.h> 29#include <vsa.h>
30#ifdef VPFX
31# define VEVENT(a) VPFX(a)
32#else
33/* For compatibility with varnish prior to 6.2 */
34# define VEVENT(a) a
35#endif
36
37/* Max. number of bytes in an IPv6 address */
38#define MU_INADDR_BYTES 16
39
40/* CIDR representation */
41struct cidr {
42 int family; /* Address family */
43 int len; /* Number of bytes in the address */
44 unsigned char address[MU_INADDR_BYTES];
45 unsigned char netmask[MU_INADDR_BYTES];
46 VSLIST_ENTRY(cidr) next;
47};
48
49typedef VSLIST_HEAD(,cidr) CIDRHEAD;
50
51/* Returns 1 if ADDR is a valid string representation of IPv4 address */
52static int
53str_is_ipv4(const char *addr, size_t len)
54{
55 int dot_count = 0;
56 int digit_count = 0;
57
58 for (; len; addr++, len--) {
59 if (!isascii(*addr))
60 return 0;
61 if (*addr == '.') {
62 if (++dot_count > 3)
63 break;
64 digit_count = 0;
65 }
66 else if (!(isdigit(*addr) && ++digit_count <= 3))
67 return 0;
68 }
69 return (dot_count == 3);
70}
71
72#define PFXSTR_IPV4_MAPPED "::ffff:"
73#define PFXLEN_IPV4_MAPPED (sizeof PFXSTR_IPV4_MAPPED - 1)
74
75static int
76str_is_ipv4mapped(const char *addr, size_t len)
77{
78 return len > PFXLEN_IPV4_MAPPED
79 && strncasecmp(PFXSTR_IPV4_MAPPED, addr, PFXLEN_IPV4_MAPPED)
80 == 0
81 && str_is_ipv4(addr + PFXLEN_IPV4_MAPPED, len - PFXLEN_IPV4_MAPPED);
82}
83
84/* Returns 1 if ADDR is a valid IPv6 address */
85static int
86str_is_ipv6(const char *addr, size_t len)
87{
88 int col_count = 0; /* Number of colons */
89 int dcol = 0; /* Did we encounter a double-colon? */
90 int dig_count = 0; /* Number of digits in the last group */
91
92 for (; len; addr++, len--) {
93 if (!isascii (*addr))
94 return 0;
95 else if (isxdigit(*addr)) {
96 if (++dig_count > 4)
97 return 0;
98 } else if (*addr == ':') {
99 if (col_count && dig_count == 0 && ++dcol > 1)
100 return 0;
101 if (++col_count > 7)
102 return 0;
103 dig_count = 0;
104 }
105 else
106 return 0;
107 }
108 return (col_count == 7 || dcol);
109}
110
111static void
112uint32_to_bytes(unsigned char *bytes, uint32_t u)
113{
114 int i;
115
116 for (i = 0; i < 4; i++) {
117 bytes[i] = u & 0xff;
118 u >>= 8;
119 }
120}
121 30
122static int 31static int
123inaddr_to_bytes(int af, void *buf, unsigned char *bytes) 32is_trusted_ip(VRT_CTX, VCL_ACL acl, char const *ipstr)
124{
125 uint32_t u;
126
127 switch (af) {
128 case AF_INET:
129 memcpy(&u, buf, sizeof u);
130 uint32_to_bytes(bytes, u);
131 return 4;
132
133 case AF_INET6:
134 memcpy(bytes, buf, 16);
135 return 16;
136 }
137
138 abort();
139}
140
141/* Fill in the BUF (LEN bytes long) with a network mask corresponding to
142 the mask length MASKLEN */
143static void
144masklen_to_netmask(unsigned char *buf, size_t len, size_t masklen)
145{
146 int i, cnt;
147
148 cnt = masklen / 8;
149 for (i = 0; i < cnt; i++)
150 buf[i] = 0xff;
151 if (i == len)
152 return;
153 cnt = 8 - masklen % 8;
154 buf[i++] = (0xff >> cnt) << cnt;
155 for (; i < len; i++)
156 buf[i] = 0;
157}
158
159#define CIDR_MAXBUFSIZE 81
160
161/* Convert string STR to CIDR. Return 0 on success and -1 on failure. */
162static int
163str_to_cidr(char const *str, struct cidr *cidr, char **endp)
164{ 33{
34 struct addrinfo hints;
35 struct addrinfo *res;
36 struct suckaddr *ip;
165 int rc; 37 int rc;
166 char *ipbuf, *ipstart;
167 union {
168 struct in_addr in;
169 struct in6_addr in6;
170 } inaddr;
171 size_t len;
172