├── .gitignore ├── README.md ├── defaults └── main.yml ├── files ├── incron.allow ├── isc-dhcp-server ├── proxmox_noreminder.sh └── root ├── handlers └── main.yml ├── meta └── main.yml ├── tasks ├── main.yml └── packer-proxmox-templates.yml ├── templates ├── dhcpd.conf.j2 ├── interfaces.j2 └── update_nat.sh.j2 └── vars └── main.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ansible-proxmox 2 | =============== 3 | 4 | The main purpose of the role is to sets up some customized networking which works for KVM and LXC. 5 | 6 | Also it enables the Free Proxmox 6 repository and it tries to automatically remove Proxmox 'No Valid Subscription' message on logins and even after upgrades. 7 | 8 | It configures a DHCP Server which will automatically assign IPs from 10 to 99 to new VM's on vmbr1 and redirect VM ports 22 and 80 via NAT to a high port like 30022 and 30080. Observe the syslog in Proxmox and see the assigned IPs and ports there. Check with ` iptables -t nat -L -n -v` 9 | 10 | Requirements 11 | ------------ 12 | 13 | Proxmox 6 already installed on the server. 14 | 15 | - check which network interfaces are seen by the server 16 | `ip a` 17 | `lshw -class network | grep logical` 18 | 19 | 20 | Role Variables 21 | -------------- 22 | 23 | The following are the most important variables to set up: 24 | 25 | proxmox_domain_name: example.org 26 | proxmox_main_ip: 192.168.1.200 27 | proxmox_gateway_ip: 192.168.1.1 28 | proxmox_domain_server: 29 | - 8.8.8.8 30 | - 8.8.4.4 31 | 32 | Example Playbook 33 | ---------------- 34 | 35 | - hosts: servers 36 | roles: 37 | - ansible-proxmox 38 | 39 | License 40 | ------- 41 | 42 | MIT 43 | 44 | Author Information 45 | ------------------ 46 | 47 | Christian Wagner 48 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for ansible-proxmox 3 | 4 | proxmox_domain_name: example.org 5 | proxmox_main_ip: 192.168.1.200 6 | proxmox_gateway_ip: 192.168.1.1 7 | proxmox_secondary_ip: 192.168.2.300 8 | proxmox_secondary_netmask: 255.255.255.0 9 | proxmox_domain_server: 10 | - 8.8.8.8 11 | - 8.8.4.4 12 | # these cannot be empty 13 | promox_add_docker_ips: 14 | - 192.168.1.210 15 | - 192.168.1.211 16 | promox_add_vm_ips: 17 | - 192.168.1.220 18 | - 192.168.1.221 19 | - 192.168.1.222 20 | 21 | # install packer-proxmox-templates and pre-requisites 22 | proxmox_templates_install: True 23 | proxmox_packer_ver: 1.5.5 24 | proxmox_templates_version: v1.7 25 | -------------------------------------------------------------------------------- /files/incron.allow: -------------------------------------------------------------------------------- 1 | root -------------------------------------------------------------------------------- /files/isc-dhcp-server: -------------------------------------------------------------------------------- 1 | # Defaults for isc-dhcp-server initscript 2 | # sourced by /etc/init.d/isc-dhcp-server 3 | # installed at /etc/default/isc-dhcp-server by the maintainer scripts 4 | 5 | # 6 | # This is a POSIX shell fragment 7 | # 8 | 9 | # Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf). 10 | #DHCPD_CONF=/etc/dhcp/dhcpd.conf 11 | 12 | # Path to dhcpd's PID file (default: /var/run/dhcpd.pid). 13 | #DHCPD_PID=/var/run/dhcpd.pid 14 | 15 | # Additional options to start dhcpd with. 16 | # Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead 17 | #OPTIONS="" 18 | 19 | # On what interfaces should the DHCP server (dhcpd) serve DHCP requests? 20 | # Separate multiple interfaces with spaces, e.g. "enp1s0f0 enp2s0". 21 | INTERFACES="vmbr1" 22 | -------------------------------------------------------------------------------- /files/proxmox_noreminder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # automatic removal of Proxmox subscription reminder during upgrades 3 | # - tested with Proxmox 4 | # 5 | # exit on error 6 | set -e 7 | 8 | # Since we are watching the whole directory, we need to check for the correct file 9 | if [ "$1" == "proxmoxlib.js.dpkg-tmp" ]; then 10 | echo "$(date +%Y-%m-%d_%H:%M) proxmoxlib.js has been upgraded - patching file" >> /var/log/incron.log 11 | 12 | # wait a bit until the file has its permanent name 13 | sleep 15 14 | # patch the files - tested with Proxmox 4.2 15 | #Proxmox4&5# cp /usr/share/pve-manager/ext6/pvemanagerlib.js /usr/share/pve-manager/ext6/pvemanagerlib.js.bak 16 | #Proxmox4&5# sed -i -r -e "s/if \(data.status !== 'Active'\) \{/if (false) {/" /usr/share/pve-manager/ext6/pvemanagerlib.js >>/var/log/incron.log 2>&1 17 | #Proxmox4&5# sed -i -r -e "s/You do not have a valid subscription for this server/This server is receiving updates from the Proxmox VE No-Subscription Repository/" /usr/share/pve-manager/ext6/pvemanagerlib.js >>/var/log/incron.log 2>&1 18 | #Proxmox4&5# sed -i -r -e "s/No valid subscription/Community Edition/" /usr/share/pve-manager/ext6/pvemanagerlib.js >>/var/log/incron.log 2>&1 19 | 20 | # patch the files 21 | cp /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.bak 22 | sed -i "s/data.status !== 'Active'/false/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js 23 | systemctl restart pveproxy.service 24 | 25 | # log the changes 26 | diff /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js.bak /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js >> /var/log/incron.log 27 | fi 28 | -------------------------------------------------------------------------------- /files/root: -------------------------------------------------------------------------------- 1 | /usr/share/javascript/proxmox-widget-toolkit/ IN_CREATE /usr/local/bin/proxmox_noreminder.sh $# 2 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for ansible-proxmox 3 | 4 | - name: restart networking 5 | service: 6 | name: networking 7 | state: restarted 8 | ignore_errors: True 9 | 10 | - name: restart isc-dhcp-server 11 | service: 12 | name: isc-dhcp-server 13 | state: restarted 14 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Christian Wagner 4 | description: Configure a Proxmox 6 server 5 | 6 | license: 7 | - MIT 8 | 9 | min_ansible_version: 2.4 10 | 11 | platforms: 12 | - name: Debian 13 | versions: 14 | - stretch 15 | - buster 16 | 17 | galaxy_tags: [] 18 | 19 | dependencies: [] 20 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 21 | # if you add dependencies to this list. 22 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for ansible-proxmox 3 | 4 | ### Proxmox repository 5 | - name: Remove Proxmox Enterprise repository 6 | apt_repository: 7 | repo: 'deb https://enterprise.proxmox.com/debian buster pve-enterprise' 8 | state: absent 9 | 10 | 11 | - name: Use Proxmox free repository 12 | apt_repository: 13 | repo: 'deb http://download.proxmox.com/debian/pve buster pve-no-subscription' 14 | state: present 15 | 16 | - name: Update APT package cache 17 | apt: 18 | update_cache: yes 19 | cache_valid_time: 7200 20 | 21 | ### Automatically remove Proxmox 'No Valid Subscription' message on upgrades 22 | - name: Install incron package 23 | apt: 24 | name: incron 25 | state: present 26 | 27 | - name: Copy incron.allow file to only allow the root user 28 | copy: 29 | src: incron.allow 30 | dest: /etc/incron.allow 31 | 32 | - name: Copy proxmox_noreminder script 33 | copy: 34 | src: proxmox_noreminder.sh 35 | dest: /usr/local/bin/proxmox_noreminder.sh 36 | mode: "u+x,g+x,o+x" 37 | 38 | - name: Copy incrontab file 39 | copy: 40 | src: root 41 | dest: /var/spool/incron/root 42 | mode: 0400 43 | 44 | ### Proxmox Networking: 45 | - name: Remove DHCP client because the server uses static IP 46 | apt: 47 | name: isc-dhcp-client 48 | state: absent 49 | purge: yes 50 | 51 | - name: Set ip forwarding on in proc and in the sysctl file and reload if necessary 52 | sysctl: 53 | name: "net.ipv4.ip_forward" 54 | value: "1" 55 | sysctl_set: yes 56 | state: present 57 | reload: yes 58 | 59 | # double-check the settings, as this could get you locked out of the server 60 | - name: Copy main network configuration 61 | template: 62 | src: interfaces.j2 63 | dest: /etc/network/interfaces 64 | notify: 65 | - restart networking 66 | 67 | # DHCP: VM's on vmbr1 will automatically receive addresses 68 | - name: Install DHCP Server 69 | apt: 70 | name: isc-dhcp-server 71 | state: present 72 | 73 | - name: DHCP config - gives out addresses 10.10.10.10 to 10.10.10.99 on vmbr1 74 | template: 75 | src: dhcpd.conf.j2 76 | dest: /etc/dhcp/dhcpd.conf 77 | notify: 78 | - restart isc-dhcp-server 79 | 80 | - name: DHCP config 81 | copy: 82 | src: isc-dhcp-server 83 | dest: /etc/default/isc-dhcp-server 84 | notify: 85 | - restart isc-dhcp-server 86 | 87 | - name: Script gets executed by DHCPD when commit expire or release event happens 88 | template: 89 | src: update_nat.sh.j2 90 | dest: /etc/dhcp/update_nat.sh 91 | mode: "u+x,g+x,o+x" 92 | 93 | - name: Add Packer templates for building Proxmox KVM images from ISO 94 | import_tasks: packer-proxmox-templates.yml 95 | when: proxmox_templates_install 96 | 97 | # ## synchronize should work here?!, copy by itself does not work 98 | # - name: Copy cluster firewall setting (off) 99 | # copy: src: ./etc/pve/firewall/cluster.fw dest: /tmp/cluster.fw 100 | # - name: Move file with shell, because /etc/pve is a fuse filesystem 101 | # shell: cp -v /tmp/cluster.fw /etc/pve/firewall/ && rm -v /tmp/cluster.fw 102 | 103 | #- name: Copy host firewall settings (off) 104 | # copy: src: ./etc/pve/local/host.fw dest: /tmp/host.fw 105 | #- name: Move file with shell, because /etc/pve is a fuse filesystem 106 | # shell: cp -v /tmp/host.fw /etc/pve/local/ && rm -v /tmp/host.fw 107 | 108 | # - name: Sync Proxmox local KVM configurations 109 | # synchronize: src: ./etc/pve/local/qemu-server/ dest: /etc/pve/local/qemu-server/ archive: no recursive: yes 110 | 111 | # - name: Sync Proxmox local LXC container configurations 112 | # synchronize: src: ./etc/pve/local/lxc/ dest: /etc/pve/local/lxc/ archive: no recursive: yes 113 | 114 | # - name: Sync Proxmox guest Firewall settings 115 | # synchronize: src: ./etc/pve/firewall/ dest: /etc/pve/firewall/ archive: no recursive: yes 116 | 117 | # - name: Sync Proxmox main configuration files (using .rsync-filter) 118 | # synchronize: src: ./etc/pve/ dest: /etc/pve/ archive: no recursive: yes 119 | 120 | # - name: Copy script to sync KVM and Proxmox Config - sync_all_vm.sh 121 | # copy: src: ./scripts/sync_all_vm.sh dest: /etc/scripts/sync_all_vm.sh mode: "u+x,g+x,o+x" 122 | # - debug: msg: "RUN the /etc/scripts/sync_all_vm.sh script ON THE SERVER!" 123 | -------------------------------------------------------------------------------- /tasks/packer-proxmox-templates.yml: -------------------------------------------------------------------------------- 1 | # Install pre-requisites for packer-proxmox-templates and make templates available 2 | 3 | - name: Ensure that prerequisites are installed. 4 | apt: 5 | name: "{{ packages }}" 6 | state: present 7 | vars: 8 | packages: 9 | - unzip 10 | - python3-pip 11 | 12 | - name: Ensure that python packages are installed 13 | pip: 14 | name: "{{ packages }}" 15 | executable: pip3 16 | vars: 17 | packages: 18 | - ansible 19 | - py-bcrypt 20 | - j2cli[yaml] 21 | 22 | - name: Ensure that Packer is downloaded. 23 | get_url: 24 | url: "https://releases.hashicorp.com/packer/{{proxmox_packer_ver}}/packer_{{proxmox_packer_ver}}_linux_amd64.zip" 25 | dest: "/tmp/packer_{{proxmox_packer_ver}}_linux_amd64.zip" 26 | 27 | - name: Ensure that Packer gets unarchived and installed. 28 | unarchive: 29 | src: "/tmp/packer_{{proxmox_packer_ver}}_linux_amd64.zip" 30 | dest: /usr/local/bin 31 | remote_src: yes 32 | 33 | - name: Make packer-templates available at /usr/local/src/packer-proxmox-templates. 34 | git: 35 | repo: 'https://github.com/chriswayg/packer-proxmox-templates.git' 36 | dest: /usr/local/src 37 | version: "{{ proxmox_templates_version }}" 38 | -------------------------------------------------------------------------------- /templates/dhcpd.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # 3 | # configuration file for ISC dhcpd for Debian 4 | # 5 | 6 | # The ddns-updates-style parameter controls whether or not the server will 7 | # attempt to do a DNS update when a lease is confirmed. We default to the 8 | # behavior of the version 2 packages ('none', since DHCP v2 didn't 9 | # have support for DDNS.) 10 | ddns-update-style none; 11 | 12 | # option definitions common to all supported networks... 13 | option domain-name "{{ proxmox_domain_name }}"; 14 | option domain-name-servers {% for dns_ip in proxmox_domain_server %}{{ dns_ip }}{% if not loop.last %},{% endif %}{% endfor %}; 15 | 16 | default-lease-time 600; 17 | max-lease-time 7200; 18 | 19 | # If this DHCP server is the official DHCP server for the local 20 | # network, the authoritative directive should be uncommented. 21 | authoritative; 22 | 23 | # Use this to send dhcp log messages to a different log file (you also 24 | # have to hack syslog.conf to complete the redirection). 25 | log-facility local7; 26 | 27 | # No service will be given on this subnet, but declaring it helps the 28 | # DHCP server to understand the network topology. 29 | 30 | # This is the subnet declaration. 31 | # use static addresses from 10.10.10.100 and above 32 | # 33 | subnet 10.10.10.0 netmask 255.255.255.0 { 34 | range 10.10.10.10 10.10.10.99; 35 | option subnet-mask 255.255.255.0; 36 | option broadcast-address 10.10.10.255; 37 | option routers 10.10.10.1; 38 | on expiry { 39 | set client_ip = binary-to-ascii(10, 8, ".", leased-address); 40 | execute("/etc/dhcp/update_nat.sh", "expiry", client_ip); 41 | } 42 | on release { 43 | set client_ip = binary-to-ascii(10, 8, ".", leased-address); 44 | execute("/etc/dhcp/update_nat.sh", "release", client_ip); 45 | } 46 | on commit { 47 | set client_ip = binary-to-ascii(10, 8, ".", leased-address); 48 | set client_hw = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); 49 | execute("/etc/dhcp/update_nat.sh", "commit", client_ip, client_hw); 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /templates/interfaces.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # 3 | # network interface settings ( Servdiscount 2020 ) 4 | # 5 | # after modifying, apply changes with: 6 | ## sleep 10 | ifdown -a && ifup -a 7 | # and restart all VMs (but often a restart of Proxmox is required) 8 | # 9 | # then check with: 10 | ## iptables -L -t nat 11 | ## netstat-nat 12 | # 13 | # Traffic is ROUTED not bridged to {{ proxmox_netw }} 14 | # Routing needs to be active: 'net.ipv4.ip_forward = 1' in /etc/sysctl.conf 15 | # check with: sysctl net.ipv4.ip_forward 16 | 17 | # The loopback network interface 18 | auto lo 19 | iface lo inet loopback 20 | 21 | # A second network adapter, if available 22 | # iface enp1s0f1 inet manual 23 | 24 | # The main physical network adapter 25 | auto {{ proxmox_netw }} 26 | iface {{ proxmox_netw }} inet static 27 | # My Main IP 28 | address {{ proxmox_main_ip }} 29 | # limit network to the main IP only 30 | netmask 255.255.255.255 31 | # the Servdiscount gateway IP 32 | pointopoint {{ proxmox_gateway_ip }} 33 | gateway {{ proxmox_gateway_ip }} 34 | # additional ips used by Docker 35 | {% for ip_added in promox_add_docker_ips %} 36 | up ip addr add {{ ip_added }}/32 dev {{ proxmox_netw }} 37 | {% endfor %} 38 | 39 | post-up echo 1 > /proc/sys/net/ipv4/conf/{{ proxmox_netw }}/proxy_arp 40 | # this is the activation of arp proxying on {{ proxmox_netw }}, to avoid confusing some network 41 | # devices or avoid being blocked by some ISP : this way, the proxy answers all the 42 | # arp requests with {{ proxmox_netw }} MAC address, instead of having each VM in the ProxMox 43 | # hypervisor answering with its own virtual MAC address. Some devices or ISP's don't 44 | # like seing one physical interface pretending to have a lot of MAC addresses. 45 | 46 | # Secondary IP on {{ proxmox_netw }} 47 | auto {{ proxmox_netw }}:1 48 | iface {{ proxmox_netw }}:1 inet static 49 | # used to access iscsi server 50 | address {{ proxmox_secondary_ip }} 51 | netmask {{ proxmox_secondary_netmask }} 52 | 53 | # Main Bridge for VMs with their own additional IP 54 | # 55 | # Typical /etc/network/interfaces for guest VM 56 | # auto eth0 57 | # iface eth0 inet static 58 | # # Additional IP 59 | # address 89.163.150.43 60 | # netmask 255.255.255.255 61 | # # The Main IP as gateway 62 | # pointopoint {{ proxmox_main_ip }} 63 | # gateway {{ proxmox_main_ip }} 64 | # 65 | auto vmbr0 66 | iface vmbr0 inet static 67 | # Bridge for routed additional IP's 68 | address {{ proxmox_main_ip }} 69 | # limit network to the main IP only 70 | netmask 255.255.255.255 71 | # we are not using bridged mode for {{ proxmox_netw }} 72 | bridge_ports none 73 | # disable Spanning Tree Protocol 74 | bridge_stp off 75 | # no forwarding delay 76 | bridge_fd 0 77 | # additional IPs must be set to 'Routed' in Servdiscount ZKM network configuration (not 'Bridged') 78 | # set a route for each of the additional virtual machine IPs 79 | {% for ip_added in promox_add_vm_ips %} 80 | up ip route add {{ ip_added }}/32 dev vmbr0 81 | {% endfor %} 82 | 83 | # Second Bridge for all of the NAT routed local IPs 84 | # 85 | # routed ports on all VMs on vmbr1 are are Internet accessible via the Main IP and all configured additional IP addresses 86 | # use PREROUTING -d 89.163.212.66 or -d 89.163.150.152 to respond only on on the respective IP address! 87 | # 88 | # - assign a new IP to each VM such as 10.10.10.VM# such as: 89 | # iface {{ proxmox_netw }} inet static 90 | # address 10.10.10.100 91 | # netmask 255.255.255.0 92 | # gateway 10.10.10.1 93 | # 94 | # - the DHCP server on Proxmox host will assign IP's in the range of 10.10.10.10 to 10.10.10.99 95 | # and automatically create iptables port forwarding for SSH and HTTP 96 | 97 | auto vmbr1 98 | iface vmbr1 inet static 99 | # Bridge for NAT routed IP's with DHCP 100 | address 10.10.10.1 101 | netmask 255.255.255.0 102 | bridge_ports none 103 | bridge_stp off 104 | bridge_fd 0 105 | # Setting up the NAT routing 106 | post-up iptables -t nat -A POSTROUTING -s '10.10.10.0/24' -o {{ proxmox_netw }} -j MASQUERADE 107 | post-down iptables -t nat -D POSTROUTING -s '10.10.10.0/24' -o {{ proxmox_netw }} -j MASQUERADE 108 | 109 | # NAT routing for ports that need to be reachable (these ports need to be open in Proxmox firewall as well) 110 | 111 | # A webserver (VM 200) 112 | # add/delete rule forward public IP and PORT to VMs private IP:PORT 113 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 20022 -j DNAT --to 10.10.10.200:22 114 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 20022 -j DNAT --to 10.10.10.200:22 115 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 443 -j DNAT --to 10.10.10.200:443 116 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 443 -j DNAT --to 10.10.10.200:443 117 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 80 -j DNAT --to 10.10.10.200:80 118 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 80 -j DNAT --to 10.10.10.200:80 119 | 120 | # A webserver (VM 220) 121 | # add/delete rule forward public IP and PORT to VMs private IP:PORT 122 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 22022 -j DNAT --to 10.10.10.220:22 123 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 22022 -j DNAT --to 10.10.10.220:22 124 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 443 -j DNAT --to 10.10.10.220:443 125 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 443 -j DNAT --to 10.10.10.220:443 126 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 80 -j DNAT --to 10.10.10.220:80 127 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 80 -j DNAT --to 10.10.10.220:80 128 | 129 | # TOR OpenBSD (VM 61121) 130 | # add/delete rule forward public IP and PORT to VMs private IP:PORT 131 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 12122 -j DNAT --to 10.10.10.121:722 132 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 12122 -j DNAT --to 10.10.10.121:722 133 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9001 -j DNAT --to 10.10.10.121:9001 134 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9001 -j DNAT --to 10.10.10.121:9001 135 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9030 -j DNAT --to 10.10.10.121:9030 136 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9030 -j DNAT --to 10.10.10.121:9030 137 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9101 -j DNAT --to 10.10.10.121:9101 138 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9101 -j DNAT --to 10.10.10.121:9101 139 | post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9130 -j DNAT --to 10.10.10.121:9130 140 | post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 9130 -j DNAT --to 10.10.10.121:9130 141 | # post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 8080 -j DNAT --to 10.10.10.121:80 142 | # post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 8080 -j DNAT --to 10.10.10.121:80 143 | # post-up iptables -t nat -A PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 8443 -j DNAT --to 10.10.10.121:443 144 | # post-down iptables -t nat -D PREROUTING -i {{ proxmox_netw }} -p tcp -d {{ proxmox_main_ip }} --dport 8443 -j DNAT --to 10.10.10.121:443 145 | -------------------------------------------------------------------------------- /templates/update_nat.sh.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # # {{ ansible_managed }} 4 | # 5 | # This script gets executed by DHCPD when the commit, expire, or release event happens 6 | # it will add port forwarding rules to make make HTTP and SSH ports publicly accessible 7 | 8 | # set server IP here 9 | server_ip="{{ proxmox_main_ip }}" 10 | netw_interface="{{ proxmox_netw }}" 11 | 12 | # Redirect stdout and stderr into the system log 13 | # Observe syslog in Proxmox and see the assigned IPs and ports there 14 | DIR=$(mktemp -d) 15 | mkfifo "$DIR/LOG_FIFO" 16 | logger -t dhcp_nat -p local0.info < "$DIR/LOG_FIFO" & 17 | exec > "$DIR/LOG_FIFO" 18 | exec 2>&1 19 | rm -rf "$DIR" 20 | 21 | echo "event $1" 22 | #echo "IP: $2" 23 | #echo "MAC: $3" 24 | 25 | # get two digits from the right of ip (works for DHCP range of 10 to 99) 26 | public_ssh="3${2:(-2)}22" 27 | public_http="3${2:(-2)}80" 28 | # forward the ports to VM 29 | vm_ip_ssh="${2}:22" 30 | vm_ip_http="${2}:80" 31 | 32 | case "$1" in 33 | commit) 34 | # check if the rule exists 35 | iptables -t nat -C PREROUTING -i $netw_interface -p tcp -d $server_ip --dport $public_ssh -j DNAT --to $vm_ip_ssh 36 | addrule=$? 37 | if [ $addrule -eq 0 ]; then 38 | echo "NAT rule exists, exiting" 39 | exit 0 40 | fi 41 | # add a forwarding rule 42 | action="activate" 43 | act="-A" 44 | ;; 45 | expiry) 46 | # expiry seems to trigger as expected 47 | # delete a forwarding rule 48 | action="remove" 49 | act="-D" 50 | ;; 51 | release) 52 | # release does not seem to trigger 53 | # delete a forwarding rule 54 | action="remove" 55 | act="-D" 56 | ;; 57 | *) 58 | echo $"Usage: commit|expiry|release" 59 | exit 1 60 | esac 61 | 62 | iptables -t nat $act PREROUTING -i $netw_interface -p tcp -d $server_ip --dport $public_ssh -j DNAT --to $vm_ip_ssh 63 | iptables -t nat $act PREROUTING -i $netw_interface -p tcp -d $server_ip --dport $public_http -j DNAT --to $vm_ip_http 64 | 65 | echo "$action SSH from public port: $public_ssh to $vm_ip_ssh" 66 | echo "$action HTTP from public port: $public_http to $vm_ip_http" 67 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for ansible-proxmox 3 | --------------------------------------------------------------------------------