В настоящее время я использую следующий сценарий, чтобы сделать несколько виртуальных машин доступными в Интернет и разрешить перенаправление некоторых портов через NAT хоста внутри сети только для хоста.
host_interface=eth0 # name of host machine interface connected to the Internet
vnet_interface=vboxnet0 # name of host machine's local network interface
host_ip[0]=... # array contains external IP addresses for every guest
guest_ip[0]=... # array contains internal IP addresses for every guest
guest_ports[0]=21,22,80,443 # array of port lists for every guest
iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD ACCEPT
iptables -F FORWARD
iptables -t nat -F
echo "1" > /proc/sys/net/ipv4/ip_forward
for i in ${!host_ip[*]}
do
iptables -t nat -A PREROUTING -i $host_interface -d ${host_ip[$i]} -p tcp -m multiport ! --dports "${guest_ports[$i]}" -j ACCEPT
iptables -t nat -A PREROUTING -i $host_interface -d ${host_ip[$i]} -j DNAT -p tcp -m multiport --dports "${guest_ports[$i]}" --to-destination ${guest_ip[$i]}
done
# forward all packets from already established connections
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
for i in ${!guest_ip[*]}
do
# allow forwarding new connections from host to guest
iptables -A FORWARD -i $host_interface -o $vnet_interface -d ${guest_ip[$i]} -m state --state NEW -j ACCEPT
# allow forwarding new connections from guest to host
iptables -A FORWARD -i $vnet_interface -o $host_interface -s ${guest_ip[$i]} -m state --state NEW -j ACCEPT
iptables -t nat -A POSTROUTING -o $host_interface -s ${guest_ip[$i]} -j SNAT --to-source ${host_ip[$i]}
done
Единственное, чего здесь не хватает, так это возможности получить доступ к любой гостевой машине по ВНЕШНЕМУ IP-адресу (конечно, в локальной сети). Я получаю сообщение «Соединение отклонено» каждый раз, когда пытаюсь подключиться к открытому порту той же машины или другого гостя (но могу подключиться к хосту с любого гостя). Внутренние (частные) IP-адреса работают нормально, я могу подключиться к любому гостю и хосту из любой точки локальной сети. Пытался добавить что-то вроде
iptables -t nat -A PREROUTING -i $vnet_interface -d ${host_ip[$i]} -j DNAT --to-destination ${guest_ip[$i]}
но кажется, что этого недостаточно.
Если я правильно понимаю, ваша проблема в том, что ваши гости виртуальной машины не могут получить доступ к себе или другим гостям по своим внешним IP-адресам. Проблема, с которой вы столкнулись, четко проиллюстрирована на эта страница (просто представьте, что маршрутизатор - это ваша виртуальная машина, а веб-сервер - одна из ваших гостевых виртуальных машин). Вам необходимо настроить «Шпильку NAT».
Решение, цитируя ту же страницу, состоит в том, что
необходимо ввести дополнительное правило NAT на [узел виртуальной машины], чтобы обеспечить, чтобы весь ответный трафик проходил через [узел виртуальной машины], несмотря на то, что клиент и сервер находятся в одной подсети.
В вашем случае такие правила могут выглядеть примерно так:
iptables -t nat -A PREROUTING -s $host_only_network -d ${guest_ip[$i]} -o $vnet_interface -p tcp -m multiport --dports "${guest_ports[$i]}" -j MASQUERADE
где:
host_only_network=192.168.1.0/24 # replace with whatever applies to your guest network
Я предоставлю вам возможность полностью отладить это, так как сложные настройки NAT имеют тенденцию вызывать у меня серьезные проблемы.
установка политики ввода по умолчанию - действительно плохая идея, вам следует использовать
iptables -P ПАДЕНИЕ ВВОДА
также пересылка по умолчанию - это плохо. Вы всегда можете установить правило, разрешающее все для трафика с определенных интерфейсов, которое всегда будет разрешено при вводе или пересылке, что нормально.