whitelisting IP in NGINX stream directive
I tried to find a solution with nginx
but did not get far; I used an http block for regular HTTP traffic (this parts works OK) and a stream block for SSL (see second part of the answer for details).
However, I think haproxy can be used here as it seems to be more flexible when configuring ACLs.
haproxy solution
global
maxconn 20000
log 127.0.0.1 local0
user haproxy
chroot /usr/share/haproxy
pidfile /run/haproxy.pid
daemon
defaults
timeout connect 10s
timeout client 30s
timeout server 30s
frontend ssl
bind *:443
mode tcp
acl network_allowed src 192.168.1.0/24 192.168.2.3/32 <-- EDIT IPs
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl dev_domain req_ssl_sni -m end .dev.mydomain.com <-- EDIT domain
tcp-request content reject if !network_allowed dev_domain
use_backend rancher_servers_https
backend rancher_servers_https
balance leastconn
mode tcp
server node1 1.2.3.4:443 fall 3 rise 2 <-- EDIT IP
server node2 2.3.4.5:443 fall 3 rise 2 <-- EDIT IP
server node3 3.4.5.6:443 fall 3 rise 2 <-- EDIT IP
I marked the place where you would need to edit the config and you'll probably need to tweak the global
section as well (depending on your distro).
The above is for the SSL part; the non-encrypted part should be similar but without the SNI/SSL parts.
Please note I haven't tried this and I have not used haproxy before but I think it will set you on the right path.
nginx solution - incomplete
I used map $ssl_preread_server_name
for getting the domain name via SNI and a geo
block for matching non-allowed IPs.
map $ssl_preread_server_name $dev_upstream {
hostnames;
*.dev.mydomain.com 1;
default 0;
}
geo $not_dev_whitelist {
default 1;
192.168.1.0/24 0;
2001:0db8::/32 0;
}
However because if
is not allowed in the stream block I can't do:
server {
listen 443;
if ($dev_upstream) {
set $dev "1";
}
if ($not_dev_whitelist) {
set $dev "${dev}1";
}
if ($dev = "11") {
return "blocked";
}
proxy_pass rancher_servers_https;
}
First Nginx does not allow nested if statements. You need to use map functionality to achieve your goal.
Second you are wrong with map implement
map "$http_referer:$arg_78up" $refernotok {
default 1;
~ mywebsite.com.*:.*$ 0;
~ ^.+:.+$ 0;
}
if ($refernotok = "1") {
return 404;
}
you should use $http_referer for your map .
First part is regular expression. ^ means start of string, .+ means one or more characters, : is a delimiter character, and then again we match one or more characters with .+, and finally we require the string ending with $. 0 is the value $refernotok variable gets when the regular expression matches.