There are a some good tutorials for this topic out there, but they are either incomplete or are missing some point on how to configure nginx properly to work as a (reverse-) proxy with vnc etc.
I assume you have proxmox installed and running on port 8006. Note that some browsers have problems with https / ssl on non-standard ports, so think about using Firefox for testing your configuration.
First but optional is to instruct proxmox to only listen to connection from localhost. Therefore, create a file /etc/default/pveproxy:
1
| sudo vim /etc/default/pveproxy |
and insert
1
2
3
| ALLOW_FROM= "127.0.0.1" DENY_FROM= "all" POLICY= "allow" |
Now proxmox only serves request from localhost.
In a next step, a reverse proxy is installed and configured using nginx. It is sufficient to install the light version of nginx for this task:
1
| sudo aptitude install nginx-light |
Now remove the link of the default nginx configuration and create your own reverse proxy configuration for proxmox that further redirects http to https:
1
2
| sudo rm /etc/nginx/sites-enabled/default sudo vim /etc/nginx/sites-enabled/proxmox |
Copy the following lines into the file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| server { listen 80; server_name _; return 301 https: // $ hostname $request_uri; } server { listen 6008 ssl; #choose your port or just use 443 server_name _; #place your domain or ip here if needed root /usr/share/nginx/www ; ssl_certificate /etc/nginx/ssl/proxmox .crt; ssl_certificate_key /etc/nginx/ssl/proxmox .key; proxy_redirect off; location ~ ^.+websocket$ { proxy_pass https: //127 .0.0.1:8006; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade" ; } location / { proxy_pass https: //127 .0.0.1:8006; } } |
Most of the directives should be self-explaining. So let’s go through only some of them in detail:
- proxy_redirect off: Do not replace upstream response-headers for HTTP/1.1 301 Moved Permanently
- proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection “upgrade”: Websockets use hop by hop header (Upgrade), the proxy should forward them instead of dropping them (default and regular behavior). See nginx websocket documentation for more information. This directives are needed by the vnc console.
This is already a working configuration. Note: nginx runs in front of proxmox now. Therefore you certificate should be the certificate for your tld. If you have to create a certificate, see SAN Server Certificate.
Test your configuration by linking and activating the proxy:
1
2
| sudo ln -s /etc/nginx/sites-available/pveproxy /etc/nginx/sites-enabled/ sudo service nginx restart |
and open the site in the browser.
Now add basic authentication as another layer of security.
Open your nginx configuration:
Open your nginx configuration:
1
| sudo vim /etc/nginx/sites-available/pveproxy |
Add the following lines before your location directives:
1
2
| auth_basic "Login" ; auth_basic_user_file /etc/nginx/ .htpasswd; |
This adds an basic authentication token before accessing the site. To generate the token, use openssl and type:
1
| printf "${username}: `openssl passwd -apr1`\n" >> /etc/nginx/ .htpasswd |
You will be prompted for a password. Type in a password and open the token to add a user to it:
1
| vim /etc/nginx/ .htpasswd |
You will see the hashed password. The username has to be added infront of the colon. Check that there is no space between the colon and the username and password. The token should have a structure like:
1
| [your_username]:[hashed_password] |
Restart nginx and check if everything is working as it mend to do.
Now lets face the firewall. I prefer using iptables directly instead of any iptable-wrapper. Here is a script in /etc/iptables/iptables.sh with basic rules that you can run as root.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
| #!/bin/bash # Firewall Script # Uses https://wiki.ubuntu.com/BasicSecurity/Firewall as basis ################################################## ##### Setting up default kernel tunings here ##### ################################################## #DROP ICMP echo-requests sent to broadcast/multi-cast addresses. echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts #DROP source routed packets echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route #Enable TCP SYN cookies echo 1 > /proc/sys/net/ipv4/tcp_syncookies #Do not ACCEPT ICMP redirect echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects #Don't send ICMP redirect echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects #Enable source spoofing protection echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter #Log impossible (martian) packets echo 1 > /proc/sys/net/ipv4/conf/all/log_martians ################################################## # Flush all previous rules ################################################## #Flush existing chains, you may add more here if you are using more chains iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -t raw -F iptables -t raw -X ################################################## #Setting up defaults etc ################################################## EXT_IP= "[your ip]" DMZ= "[your internal network e.g. 192.168.1.0/24]" #Allow traffic on loopback iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT #Creating default policies iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP #If we're not a router #Allow previously established connections iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT #Drop all packets with invalid headers or checksums iptables -A INPUT -m conntrack --ctstate INVALID -j DROP # Forward chain iptables -A FORWARD -d $DMZ -j ACCEPT iptables -A FORWARD -s $DMZ -j ACCEPT ########################################################### #### Allow inbound connections on the ports we decided #### ########################################################### iptables -A INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow HTTP" iptables -A INPUT -p tcp --dport 6008 -j ACCEPT -m comment --comment "Allow HTTPS" iptables -A INPUT -p tcp --dport 443 -j ACCEPT -m comment --comment "Allow HTTPS" iptables -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT -m comment --comment "Allow SSH" ########################################################### #### Allow outbound connections on the ports we decided ### ########################################################### # System related iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT -m comment --comment "DNS" iptables -A OUTPUT -p udp --dport 53 -j ACCEPT -m comment --comment "DNS" iptables -A OUTPUT -p udp --dport 67:68 -j ACCEPT -m comment --comment "DHCP" iptables -A OUTPUT -p udp --dport 123 -j ACCEPT -m comment --comment "NTP" # Email related iptables -A OUTPUT -p tcp --dport 465 -j ACCEPT -m comment --comment "Allow SSL SMTP" iptables -A OUTPUT -p tcp --dport 993 -j ACCEPT -m comment --comment "Allow SSL IMAP" # VNC related #iptables -A OUTPUT -p tcp --dport 5900:5999 -j ACCEPT -m comment --comment "Allow VNC" #iptables -A INPUT -p tcp --dport 5900:5999 -j ACCEPT -m comment --comment "Allow VNC" # Web access iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow HTTP" iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT -m comment --comment "Allow HTTPS" # VM relatad iptables -t nat -A POSTROUTING -s $DMZ -o [outgoing interface, e.g. eth0] -j SNAT --to- source $EXT_IP -m comment --comment "Nating" ########################################################### # Allow bidirectional connections on the ports we decided # ########################################################### # Allow ICMP ping incoming client request iptables -A INPUT -p icmp --icmp- type echo -request -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow incoming pings" iptables -A OUTPUT -p icmp --icmp- type echo -reply -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow incoming pings" # Allow outgoing ping request iptables -A OUTPUT -p icmp --icmp- type echo -request -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow outgoing pings" iptables -A INPUT -p icmp --icmp- type echo -reply -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow outgoing pings" #Set up logging for incoming traffic. Just comment out the following lines #iptables -N LOGNDROP #iptables -A INPUT -j LOGNDROP #iptables -A LOGNDROP -j LOG #iptables -A LOGNDROP -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 7 #iptables -A LOGNDROP -j DROP #Save our firewall rules iptables-save > /etc/iptables/iptables .up.rules |
This blocks everything except the defined ports in the INPUT and OUTPUT chain.
Important note: The rules in the forward chain are necessary for the NAT process which happens in the POSTROUTING chain (SNAT)
Important note: The rules in the forward chain are necessary for the NAT process which happens in the POSTROUTING chain (SNAT)
To start these rules on machine boot, make the created rule-set executable and add a file /etc/network/if-pre-up.d/iptables. Add the following lines and make it executable, too.
1
2
| #!/bin/sh /sbin/iptables-restore < /etc/iptables/iptables .up.rules |
If you are also using IPv6, you have to create another rule-set with ip6tables!
Further security measures:
- Use fail2ban
- Use rootkit hunter or a similar tool
- Use TCP-Wrapper (/etc/hosts.deny any /etc/hosts.allow)
Have fun with your reasonable safe server
Post A Comment:
0 comments:
Post a Comment