Skip to content

Instantly share code, notes, and snippets.

@moycat
Created March 6, 2020 03:29
Show Gist options
  • Save moycat/74f422be38366b5575f2218b862b019e to your computer and use it in GitHub Desktop.
Save moycat/74f422be38366b5575f2218b862b019e to your computer and use it in GitHub Desktop.
Utils for port forwarding using iptables on a single NIC Proxmox VE machine. Suppose your intranet subnet is 192.168.0.0/24, the public IP is 1.2.3.4 & the NIC is vmbr0.
#!/usr/bin/env python3
import argparse
import ipaddress
import os
INTERNAL_SUBNET = "192.168.0.0/24"
INTERNET_ADDRESS = "1.2.3.4"
INTERFACE = "vmbr0"
def get_args():
parser = argparse.ArgumentParser(description="Add a port forwarding rule.")
parser.add_argument("--port", type=int, metavar="{1...65535}", help="Host port where traffic comes from.",
required=True)
parser.add_argument("--protocol", type=str, help="Port protocol to use.", choices=("tcp", "udp", "all"),
default="tcp")
parser.add_argument("internal_address", type=str, help="Internal address to be forwarded to.")
args = parser.parse_args()
listen_port = args.port
if not 0 < listen_port < 65536:
parser.error("invalid host port")
protocols = (args.protocol,) if args.protocol != "all" else ("tcp", "udp")
internal_address = args.internal_address
ip, separator, port = internal_address.rpartition(":")
try:
assert separator
assert ipaddress.ip_address(ip) in ipaddress.ip_network(INTERNAL_SUBNET)
port = int(port)
assert 0 < port < 65536
except Exception as _:
parser.error("invalid internal address")
return listen_port, ip, port, protocols
def main():
listen_port, internal_ip, internal_port, protocols = get_args()
print("executing iptables commands...")
for protocol in protocols:
commands = (
f"iptables -t nat -A PREROUTING -d {INTERNET_ADDRESS}/32 -i {INTERFACE} -p {protocol} "
f"--dport {listen_port} -j DNAT --to-destination {internal_ip}:{internal_port}",
f"iptables -A FORWARD -d {internal_ip}/32 -p {protocol} --dport {internal_port} "
f"-m state --state NEW,ESTABLISHED,RELATED -j ACCEPT",
)
for c in commands:
print(c)
os.system(c)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
import argparse
import ipaddress
import os
INTERNAL_SUBNET = "192.168.0.0/24"
INTERNET_ADDRESS = "1.2.3.4"
INTERFACE = "vmbr0"
def get_args():
parser = argparse.ArgumentParser(description="Delete a port forwarding rule.")
parser.add_argument("--port", type=int, metavar="{1...65535}", help="Host port where traffic comes from.",
required=True)
parser.add_argument("--protocol", type=str, help="Port protocol to use.", choices=("tcp", "udp", "all"),
default="tcp")
parser.add_argument("internal_address", type=str, help="Internal address to be forwarded to.")
args = parser.parse_args()
listen_port = args.port
if not 0 < listen_port < 65536:
parser.error("invalid host port")
protocols = (args.protocol,) if args.protocol != "all" else ("tcp", "udp")
internal_address = args.internal_address
ip, separator, port = internal_address.rpartition(":")
try:
assert separator
assert ipaddress.ip_address(ip) in ipaddress.ip_network(INTERNAL_SUBNET)
port = int(port)
assert 0 < port < 65536
except Exception as _:
parser.error("invalid internal address")
return listen_port, ip, port, protocols
def main():
listen_port, internal_ip, internal_port, protocols = get_args()
print("executing iptables commands...")
for protocol in protocols:
commands = (
f"iptables -t nat -D PREROUTING -d {INTERNET_ADDRESS}/32 -i {INTERFACE} -p {protocol} "
f"--dport {listen_port} -j DNAT --to-destination {internal_ip}:{internal_port}",
f"iptables -D FORWARD -d {internal_ip}/32 -p {protocol} --dport {internal_port} "
f"-m state --state NEW,ESTABLISHED,RELATED -j ACCEPT",
)
for c in commands:
print(c)
os.system(c)
if __name__ == "__main__":
main()
#!/bin/sh
echo "reloading IPv4 rules from iptables-persistent..."
iptables --flush
iptables --table nat --flush
iptables --delete-chain
iptables --table nat --delete-chain
iptables -F
iptables -X
iptables-restore < /etc/iptables/rules.v4
# Initial iptables config for NAT.
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.0.0/24 -o vmbr0 -j SNAT --to-source 1.2.3.4
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -s 192.168.0.0/24 -i vmbr0 -o vmbr0 -j ACCEPT
-A FORWARD -i vmbr0 -o vmbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
#!/bin/sh
echo "saving IPv4 rules for iptables-persistent..."
iptables-save > /etc/iptables/rules.v4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment