Вот вам скрипты для установления GRE туннеля. Первый предназначен для геймсервера, второй - для зеркала.
То, что надо заменить:
GS_PRV_IP - замените на ИП адрес геймсервера
PS_PRV_IP - замените на ИП адрес зеркала
GS_PORT - замените на порт геймсервера
TUN_IP_MASK - уникальный ИП адрес туннеля, который вы задаёте. Если у вас есть несколько зеркал, замените на ИП адрес в последовательности, например:
172.16.10,
172.16.11,
172.16.12 и т.д.
TUN_NAME - уникальное имя зеркала, например
gre-proxy-us,
gre-proxy-eu,
gre-proxy-ru и т.д.
TUN_ROUTE_NAME - уникальное имя таблицы маршрутизации. Пусть оно будет похоже на уникальное имя зеркала
IF_NAME - имя сетевого интерфейса, предоставляющего публичный ИП адрес (PS_PRV_IP), проверьте его через команду
ip a
Также, нужно подтвердить, что у зеркала включено
net.ipv4.ip_forward=1 в
/etc/sysctl.conf. Проверяем через команду
sysctl -n net.ipv4.ip_forward, если результат
0, то оно выключено и надо включить через команды
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf и
sysctl -p.
Если всё хорошо и скрипты сработали, тогда проверяем связь:
Пишем команды
ping 172.16.10.1 и
ping 172.16.10.2 (или TUN_IP_MASK, которое вы задали) в зеркало и геймсервера. Если есть ответ, то туннель работает.
Затем геймсервер привязывается к локальному ИП адресу туннеля (172.16.10.1), но игрокам показывает ИП зеркала. Например, моя конфигурация выглядит следующим образом:
XML:
<gameserver id="3" bindAddress="172.16.10.1" externalAddress="98.125.65.186" bindPort="7777">
Таким образом весь трафик зеркала<->геймсервера проходит через туннель (172.16.10.2 и 172.16.10.1 соответственно), и все пакеты сохраняют реальный ИП адрес игрока. Короче, зеркало превращается в обычный роутер, который у вас в доме.
Bash:
#!/bin/bash
GS_PRV_IP="202.187.6.133" # IP address of the gameserver machine.
PS_PRV_IP="98.125.65.186" # IP address of the proxy machine.
TUN_IP_MASK="172.16.10" # Unique IP address (except the last part) set by you, which will be the IP address of the local network we are creating.
TUN_LOCAL_IP="${TUN_IP_MASK}.1" # Do not change. IP address of the gameserver machine within the tunnel network.
TUN_REMOTE_IP="${TUN_IP_MASK}.2" # Do not change. IP address of the proxy machine within the tunnel network.
TUN_NAME="gre-proxy-us" # Interface name of the tunnel.
TUN_ROUTE_NAME="proxy-us" # name of the routing table.
TUN_ROUTE_PRIO="10" # priority of the routing
echo ""
echo "================================================================================"
echo "This script must be run on the gameserver machine."
echo "================================================================================"
echo ""
echo "Check inside this script's commented sections. There are some prerequisites that must be met. Also run this script as root or sudo."
echo "Gameserver (this machine) private IP for tunneling is set to: $GS_PRV_IP"
echo "Proxy private IP for tunneling is set to: $PS_PRV_IP"
echo "Tunnel local IP (this machine) is set to: $TUN_LOCAL_IP"
echo "Tunnel remote IP (proxy machine) is set to: $TUN_REMOTE_IP"
echo "Tunnel name is set to: $TUN_NAME"
while true
do
read -r -p 'Do you want to continue? ' choice
case "$choice" in
n|N) exit 0;;
y|Y) break ;;
*) echo 'Response not valid. Please enter y or n';;
esac
done
echo ""
echo "Creating the tunnel..."
echo "Creating tunnel interface $TUN_NAME tunneling $GS_PRV_IP -> $PS_PRV_IP"
ip tunnel add $TUN_NAME mode gre remote $PS_PRV_IP local $GS_PRV_IP ttl 255
if [ $? -ne 0 ]; then
exit $?
fi
echo "Creating tunnel IP $TUN_LOCAL_IP -> $TUN_REMOTE_IP"
ip addr add $TUN_LOCAL_IP peer $TUN_REMOTE_IP dev $TUN_NAME
if [ $? -ne 0 ]; then
exit $?
fi
echo "Setting tunnel interface up."
ip link set $TUN_NAME up
if [ $? -ne 0 ]; then
exit $?
fi
echo "Adding the routing table to /etc/iproute2/rt_tables"
echo "${TUN_ROUTE_PRIO} ${TUN_ROUTE_NAME}" >> /etc/iproute2/rt_tables
if [ $? -ne 0 ]; then
exit $?
fi
echo "Enabling the use of the routing table."
ip route add default via $TUN_REMOTE_IP dev $TUN_NAME src $TUN_LOCAL_IP table $TUN_ROUTE_NAME
if [ $? -ne 0 ]; then
exit $?
fi
echo "Adding routing rules."
# We need to append "protocol kernel" to the ip rule, so systemd-networkd doesn't decide to automatically
# delete our rule and mess-up the routing :@:@:@:@:@:@:@:@:@
# this screwed us so bad!!!!
# If rule is broken and there is rp_filter=1, the packets coming from the tunnel will be marked as "martian" packets.
ip rule add from $TUN_LOCAL_IP table $TUN_ROUTE_NAME prio $TUN_ROUTE_PRIO proto kernel
if [ $? -ne 0 ]; then
exit $?
fi
echo ""
# Add those to the networkd configuration, so it doesn't delete our rules!!!
echo "Make the following changes at \"/etc/systemd/networkd.conf\", so systemd doesn't randomly change your rules..."
echo "ManageForeignRoutingPolicyRules=no"
echo "ManageForeignRoutes=no"
echo "service systemd-networkd reload"
echo ""
echo ""
echo "All done."
echo "Time for you to test if the connection is active and working."
Bash:
#!/bin/bash
# Make sure ipv4 ip forwarding is enabled there:
# echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
# Then reload the config:
# sysctl -p
#
# Also make sure no such tunnel name exists.
# You can delete existing tunnels by calling:
# ip link set $TUN_NAME down
# ip tunnel del $TUN_NAME
#
# Other helpful changes to /etc/sysctl.conf are:
# net.ipv4.tcp_syncookies=1
# net.ipv4.conf.default.rp_filter=1
# net.ipv4.conf.all.rp_filter=1
#
# These variables below must be changed by you:
GS_PORT="7777"
PS_PRV_IP="98.125.65.186" # IP address of proxy machine.
GS_PRV_IP="202.187.6.133" # IP address of gameserver machine.
TUN_IP_MASK="172.16.10" # Unique IP address (except the last part) set by you, which will be the IP address of the local network we are creating.
TUN_IP_REMOTE="${TUN_IP_MASK}.1" # Do not change. IP address of the gameserver machine within the tunnel network.
TUN_IP_LOCAL="${TUN_IP_MASK}.2" # Do not change. IP address of the proxy machine within the tunnel network.
TUN_NAME="gre-main-gs" # Interface name of the tunnel.
IF_NAME="ens3" # Interface name of the network card from which the traffic comes. Usually it is the interface name, which provides the PS_PRV_IP, check via "ip a" command.
echo ""
echo "================================================================================"
echo "This script must be run on the proxy machine."
echo "================================================================================"
echo ""
echo "Check inside this script's commented sections. There are some prerequisites that must be met. Also run this script as root or sudo."
echo "Gameserver port is set to: $GS_PORT"
echo "Gameserver private IP for tunneling is set to: $GS_PRV_IP"
echo "Proxy (this proxy) private IP for tunneling is set to: $PS_PRV_IP"
echo "Tunnel remote IP (main machine) is set to: $TUN_IP_REMOTE"
echo "Tunnel local IP (this proxy) is set to: $TUN_IP_LOCAL"
echo "Tunnel name is set to: $TUN_NAME"
echo "Interface name (public one from where people connect to this proxy, check |ip link show| or |ip addr show|) is set to: $IF_NAME"
while true
do
read -r -p 'Do you want to continue? ' choice
case "$choice" in
n|N) exit 0;;
y|Y) break ;;
*) echo 'Response not valid. Please enter y or n';;
esac
done
# Create the gre tunnel:
echo "Checking if ip_forward is enabled"
if [ $(sysctl -n net.ipv4.ip_forward) -eq 0 ]; then
while true
do
read -r -p 'IP forwarding is disabled. Would you like to enable it? ' choice
case "$choice" in
n|N) exit 0;;
y|Y) break ;;
*) echo 'Response not valid. Please enter y or n';;
esac
done
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
if [ $? -ne 0 ]; then
echo "Failed to enable ip_forward. You need to manually open '/etc/sysctl.conf' and place 'net.ipv4.ip_forward=1' at the end of the file. Then reload the changes by executing 'sysctl -p'"
exit $?
fi
sysctl -p
if [ $? -ne 0 ]; then
echo "Failed to execute: sysctl -p"
exit $?
fi
fi
# Create the gre tunnel:
echo ""
echo "Creating the tunnel..."
echo "Creating tunnel interface $TUN_NAME tunneling $PS_PRV_IP -> $GS_PRV_IP"
ip tunnel add $TUN_NAME mode gre local $PS_PRV_IP remote $GS_PRV_IP ttl 255
if [ $? -ne 0 ]; then
exit $?
fi
echo "Creating tunnel IP $TUN_IP_LOCAL -> $TUN_IP_REMOTE"
ip addr add $TUN_IP_LOCAL peer $TUN_IP_REMOTE dev $TUN_NAME
if [ $? -ne 0 ]; then
exit $?
fi
echo "Setting tunnel interface up."
ip link set $TUN_NAME up
if [ $? -ne 0 ]; then
exit $?
fi
# Add the firewall rules. Make sure we setup the routing rule.
# We use -I (insert) mode instead of -A (append) mode for GRE protocol because of some weird firewall configurations we might encounter that prevent us from connecting to gre tunnel.
echo ""
echo "Adding firewall rules..."
echo "Setting the routing rule for port $GS_PORT to be routed to $TUN_IP_REMOTE"
iptables -A PREROUTING -t nat -i $IF_NAME -p tcp -m tcp --dport $GS_PORT -j DNAT --to-destination ${TUN_IP_REMOTE}:${GS_PORT}
if [ $? -ne 0 ]; then
exit $?
fi
# Make sure GRE tunnel is not blocked by firewall
echo "Opening gre protocol for IP $GS_PRV_IP"
iptables -I INPUT -s ${GS_PRV_IP}/32 -p gre -j ACCEPT
if [ $? -ne 0 ]; then
exit $?
fi
echo ""
echo "All done."
echo "Check your ip links (type: ip link show) to verify the tunnel has been created."
echo "Check your tunnel ips (type: ip addr show) to verify the correct tunnel IPs have been set."
echo "Check your firewall rules to make sure they are not conflicting with each other (gre protocol is allowed for ip $GS_PRV_IP and port $GS_PORT is being routed to $TUN_IP_REMOTE)"
echo ""
echo "Next, test your traffic through the GRE tunnel:"
echo " tcpdump -i $IF_NAME"
echo "This will show you if this proxy is configured properly to accept traffic through the GRE tunnel from the remote server."
echo "You will need to type the same command on the remote server (but change the interface name to correspond to the name there, because they might not be the same) to check if traffic is coming and going in both ways."
echo "To generate traffic, the easiest way is to try and enter a ssh session through the tunnel ip. Which is $TUN_IP_REMOTE when testing from this machine to remote machine and $TUN_IP_LOCAL when testing from remote machine to this machine."
echo "If ssh ports are opened for those IPs, you should be able to connect to a ssh session from both sides."
echo ""
echo "Finally test that the proxy is working:"
echo "Execute this at the gameserver machine to listen for incoming traffic on the gameserver port:"
echo " netcat -l $TUN_IP_REMOTE $GS_PORT"
echo "Then go to a machine outside of this network (machine that is neither the proxy or the gameserver one) and try to connect to the proxy's public IP which should be routing traffic."
echo " telnet PROXY.PUBLIC.IP.HERE $GS_PORT"
echo "This should establish a connection that is being proxied through this proxy machine towards the gameserver. Whatever you type in the telnet should appear on the gameserver machine and whatever you type on the netcat should appear on the outside machine."