Nginx restricting access by machine name instead of IP address - nginx

I use nginx with simple auth rules such as the following:
location /api {
#...
deny 192.168.1.2;
allow 10.128.99.1;
allow 127.0.0.1;
deny all;
}
This works great, but sometimes a users IP changes, then I have to update the nginx.conf file with the new IP. Is there any way to use machine name instead, such as the following:
location /api {
#...
deny 192.168.1.2;
allow MachineName;
allow 127.0.0.1;
deny all;
}
I tried that, but nginx gave an error when I tried to start the service. I can use ping to look up the IP, but I am just trying to automate the process. Thanks in advance.

There is Nginx HTTP rDNS module which allows doing just the very thing you're asking about:
This module allows to make a reverse DNS (rDNS) lookup for incoming connection and provides simple access control of incoming hostname by allow/deny rules
The only downside is that you'll have to disable HTTP/1.1 keepalive due to outstanding bug, which was never fixed.
Installation on CentOS systems (6, 7 and 8) can be done using commercial GetPageSpeed repository (requires subscription):
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install nginx-module-rdns

Related

How to redirect ssh requests in Nginx?

I'm using the gitea versioning system in a docker environment. The gitea used is a rootless type image.
The http port mapping is “8084:3000” and the ssh port mapping is “2224:2222”.
I generated the keys on my Linux host and added the generated public key to my Gitea account.
1.Test environment
Later I created the ssh config file nano /home/campos/.ssh/config :
Host localhost
HostName localhost
User git
Port 2224
IdentityFile ~/.ssh/id_rsa
After finishing the settings i created the myRepo repository and cloned it.
To perform the clone, I changed the url from ssh://git#localhost:2224/campos/myRepo.git to git#localhost:/campos/myRepo.git
To clone the repository I typed: git clone git#localhost:/campos/myRepo.git
This worked perfectly!
2.Production environment
However, when defining a reverse proxy and a domain name, it was not possible to clone the repository.
Before performing the clone, I changed the ssh configuration file:
Host gitea.domain.com
HostName gitea.domain.com
User git
Port 2224
IdentityFile ~/.ssh/id_rsa
Then I tried to clone the repository again:
git clone git#gitea.domain.com:/campos/myRepo.git
A connection refused message was shown:
Cloning into 'myRepo'...
ssh: connect to host gitea.domain.com port 2224: Connection refused
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
I understand the message is because by default the proxy doesn't handle ssh requests.
Searching a bit, some links say to use "stream" in Nginx.
But I still don't understand how to do this configuration. I need to continue accessing my proxy server on port 22 and redirect port 2224 of the proxy to port 2224 of the docker host.
The gitea.conf configuration file i use is as follows:
server {
listen 443 ssl http2;
server_name gitea.domain.com;
# SSL
ssl_certificate /etc/nginx/ssl/mycert_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/mycert.key;
# logging
access_log /var/log/nginx/gitea.access.log;
error_log /var/log/nginx/gitea.error.log warn;
# reverse proxy
location / {
proxy_pass http://192.168.10.2:8084;
include myconfig/proxy.conf;
}
}
# HTTP redirect
server {
listen 80;
server_name gitea.domain.com;
return 301 https://gitea.domain.com$request_uri;
}
3. Redirection in Nginx
I spent several hours trying to understand how to configure Nginx's "stream" feature. Below is what I did.
At the end of the nginx.conf file I added:
stream {
include /etc/nginx/conf.d/stream;
}
In the stream file in conf.d, I added the content below:
upstream ssh-gitea {
server 10.0.200.39:2224;
}
server {
listen 2224;
proxy_pass ssh-gitea;
}
I tested the Nginx configuration and restart your service:
nginx -t && systemctl restart nginx.service
I viewed whether ports 80,443, 22 and 2224 were open on the proxy server.
ss -tulpn
This configuration made it possible to perform the ssh clone of a repository with a domain name.
4. Clone with ssh correctly
After all the settings I made, I understood that it is possible to use the original url ssh://git#gitea.domain.com:2224/campos/myRepo.git in the clone.
When typing the command git clone ssh://git#gitea.domain.com:2224/campos/myRepo.git, it is not necessary to define the config file in ssh.
This link helped me:
https://discourse.gitea.io/t/password-is-required-to-clone-repository-using-ssh/5006/2
In previous messages I explained my solution. So I'm setting this question as solved.

Send nginx logs to google cloud logging from OVH VPS

I have an OVH VPS with nginx server setup on it. I'm looking for a way to send nginx access and error logs to Google Cloud Logging service, but all info I could find was about sending logs from Google Cloud VMs. Is it even possible at this moment? I've tried also to find anything about sending syslog to GCP as a workaround but no luck too. Since my dotnet services succesfully send logs to GCP I suppose it should be possible. Any suggestions?
In GCP there is an integration with NGINX to collect connection metrics and access logs. There are some prerequisites that you need to accomplish before you start collecting logs from NGINX.
You must install Ops Agent in your instance . The Ops Agent collects logs and metrics on Compute Engine instances, sending your logs to Cloud Logging and your metrics to Cloud Monitoring. If you are using a single VM on a Linux SO, you can install the agent with the following command:
curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
sudo bash add-google-cloud-ops-agent-repo.sh --also-install
You can consult the details about the Ops Agent installation on this link
You will need to configure your NGINX instance enabling the stub_status module in the nginx configuration file to set up a locally reachable URL, like the following example:
http://www.example.com/status
If you don't have the stub_status module enabled, you can run the following command to enable it:
sudo tee /etc/nginx/conf.d/status.conf > /dev/null << EOF
server {
listen 80;
server_name 127.0.0.1;
location /status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
location / {
root /dev/null;
}
}
EOF
sudo service nginx reload
curl http://127.0.0.1:80/status
Please note that: 127.0.0.1 can be replaced with the real server name, for example, server_name mynginx.domain.com.
All these steps are detailed in the following link, it is a guide to setup all the prerequisites before you start collecting logs from your NGINX deployment. Also, there is an example to configure your deployment

Nginx resolver for Kubernetes with skydns

I can't find a way to make an nginx pod resolve another kubernetes services URLs.
I am NOT using kube-dns , we are using kube2sky solely and we are not going to implement kube-dns yet, so I need to fix in this scenario.
For example, I want nginx to resolve a service URL app.mynamespace.svc.skydns.local but if I run a ping to that URL it resolves successfully.
My nginx config part is:
location /api/v1/namespaces/mynamespace/services/app/proxy/ {
resolver 127.0.0.1
set \$endpoint \"http://app.mynamespace.svc.skydns.local/\";
proxy_pass \$endpoint;
proxy_http_version 1.1;
proxy_set_header Connection \"upgrade\";
}
I need to specify the target upstream in a variable because I want nginx to starts even if the target is not available, if I don't specify in variable nginx crashes when starting up because the upstream needs to be available and resolvable.
The problem I think is the resolver value, I've tried with 127.0.0.1, with 127.0.0.11, and with the skydns IP specified in configuration 172.40.0.2:53:
etcdctl get /skydns/config
{"dns_addr":"0.0.0.0:53","ttl":4294967290,"nameservers":["172.40.0.2:53"]}
But nginx cannot resolve the URL yet.
What IP should I specify in the resolver field in nginx config for kubernetes and skydns config?
Remember that we don't have kube-dns.
Thank you.
I don't think resolving app.mynamespace.svc.skydns.local has anything to do with configuring the upstream DNS servers. Generally, for that, you configure a well-known DNS server like 8.8.8.8 or your cloud infrastructure DNS server which would be perhaps 172.40.0.2. For example as described in the docs:
$ curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/config \
-d value='{"dns_addr":"127.0.0.1:5354","ttl":3600, "nameservers": ["8.8.8.8:53","8.8.4.4:53"]}'
You might want to check the logs of your kube2sky2 pod, for any guidance and that all the config options are specified like --kube-master-url, --etcd-server. Maybe it can't talk to the Kubernetes master and receive updates of running pods so that the SRV entries get updates.

Nginx and OpenVPN - controlling access to wordpress configuration files

I'm coming with a question and struggling because I already made setup LEMP + CSF FireWall + Nginx WordPress block + OpenVPN.
So - I have a problem with blocking access to wp-login.php file and /wp-admin directory at the server.
Already I made successful blocking for anybody there, but I can't make access for connections from VPN tunneling.
Legend:
IP: 1.1.1.1 - server IP
IP: 10.8.0.2 - IP what I've got at VPN connection
It's my location blocking block at nginx:
location ~ ^/(wp-admin|wp-login\.php) {
allow 1.1.1.1;
deny all;
}
It's my OpenVPN conf file:
port 1194
proto udp
dev tun
sndbuf 0
rcvbuf 0
ca ca.crt
cert server.crt
key server.key
dh dh.pem
auth SHA512
tls-auth ta.key 0
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
cipher AES-256-CBC
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3
crl-verify crl.pem
I tried to allow connections for 10.8.0.0/24 and for server IP... and still, I'm getting error 403 when I'm trying to get there through VPN.
Edit
I tried to add redirection to VPN push "redirect-gateway def1" and in location blocks, I changed from 1.1.1.1 to 10.8.0.0/24 and still nothing (even with 1.1.1.1 don't work).
Edit 2
I changed assigned IP from VPN to the client 16.8.*.* (/24) address. I can't access to file (wp-*) when I'm giving in block allow 1.1.1.1; allow 16.8.0.0/24; deny all.
It's training VPS so I can struggle more with it :D
What could be happening is that you are trying to access your site using the public IP of your VPN but not the private, seems that you already tried this:
location ~ ^/(wp-admin|wp-login\.php) {
allow 1.1.1.1;
allow 10.80.0.0/24;
deny all;
}
But now try to check what is current IP doing the request, give a try to this:
location /myip {
default_type text/plain;
return 200 "$remote_addr\n";
}
And then query yoursite/myip it should print the IP you are using to access and the one probably you want to only allow. (in case is a public IP probably the IP will match the one printed here https://myip.country/ip)

Restricting direct access to port, but allow port forwarding in Nginx

I'm trying to restrict direct access to elasticsearch on port 9200, but allow Nginx to proxy pass to it.
This is my config at the moment:
server {
listen 80;
return 301;
}
server {
listen *:5001;
location / {
auth_basic "Restricted";
auth_basic_user_file /var/data/nginx-elastic/.htpasswd;
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
}
}
This almost works as I want it to. I can access my server on port 5001 to hit elasticsearch and must enter credentials as expected.
However, I'm still able to hit :9200 and avoid the HTTP authentication, which defeats the point. How can I prevent access to this port, without restricting nginx? I've tried this:
server {
listen *:9200;
return 404;
}
But I get:
nginx: [emerg] bind() to 0.0.0.0:9200 failed (98: Address already in use)
as it conflicts with elasticsearch.
There must be a way to do this! But I can't think of it.
EDIT:
I've edited based on a comment and summarised the question:
I want to lock down < serverip >:9200, and basically only allow access through port 5001 (which is behind HTTP Auth). 5001 should proxy to 127.0.0.1:9200 so that elasticsearch is accessible only through 5001. All other access should 404 (or 301, etc).
add this in your ES config to ensure it only binds to localhost
network.host: 127.0.0.1
http.host: 127.0.0.1
then ES is only accessible from localhost and not the world.
make sure this is really the case with the tools of your OS. e.g. on unix:
$ netstat -an | grep -i 9200
tcp4 0 0 127.0.0.1.9200 *.* LISTEN
in any case I would lock down the machine using the OS firewall to really only allow the ports you want and not only rely on proper binding. why is this important? because ES also runs its cluster communication on another port (9300) and evil doers might just connect there.

Resources