假设云主机eth0: 47.93.27.106
tun0: inet 10.8.0.1 netmask 255.255.255.0
Show rules for a specific zone (public)
sudo firewall-cmd --zone=public --list-all
Add the tun0
interface to the public
zone:
sudo firewall-cmd --zone=public --add-interface=tun0 --permanent
Check the active zones again to confirm that tun0
has been added:
sudo firewall-cmd --get-active-zones
Add the forward port rules
sudo firewall-cmd --zone=public --add-forward-port=port=14662:proto=tcp:toport=4662:toaddr=10.8.0.2 --permanent
(10.8.0.1)开放端口14662 接收外部流量, 转发到10.8.0.2:4662
修改内核参数支持IPv4转发
sudo sysctl -w net.ipv4.ip_forward=1
sudo sh -c 'echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf'
配置NAT确保public zone的流量转到en0:
sudo iptables -t nat -A PREROUTING -p tcp --dport 14662 -j DNAT --to-destination 10.8.0.2:4662
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
确保iptables-serverices软件包安装了
sudo yum install iptables-services
保存、重启iptables,让配置生效
sudo service iptables save
sudo systemctl restart iptables
sudo systemctl enable iptables
重启防火墙firewalld
sudo firewall-cmd --reload
sudo systemctl restart firewalld
查看改动的配置
sudo firewall-cmd --list-all --zone=public
sudo iptables -L -t nat
在这台VPS上 telnet 10.8.0.2 4662
windows客户端先连接上Open***, 另一台vps
当然也可以用在线工具open-ports, TCP可以支持, UDP还是要自己写个简单的代码测试。
windows客户端
同理udp 4672
sudo firewall-cmd --zone=public --add-forward-port=port=14672:proto=udp:toport=4672:toaddr=10.8.0.2
sudo firewall-cmd --zone=public --add-forward-port=port=14672:proto=udp:toport=4672:toaddr=10.8.0.2 --permanent
sudo firewall-cmd --reload
sudo iptables -t nat -A PREROUTING -p udp --dport 14672 -j DNAT --to-destination 10.8.0.2:4672
sudo service iptables save
sudo systemctl restart firewalld
发送UDP报文
echo -n "Test UDP Packet" | nc -u 47.93.27.106 14672 # 以下C代码同理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <server_ip> <server_port> <message>\n", argv[0]);
exit(EXIT_FAILURE);
}
const char *server_ip = argv[1];
int server_port = atoi(argv[2]);
const char *message = argv[3];
int sockfd;
struct sockaddr_in server_addr;
// Create socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
// Fill server information
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(server_port);
server_addr.sin_addr.s_addr = inet_addr(server_ip);
// Send UDP packet
if (sendto(sockfd, message, strlen(message), 0, (const struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
perror("Send failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("UDP packet sent.\n");
// Close socket
close(sockfd);
return 0;
}
云主机VPS发到本地Windows:
打开wireshark找到tunnel adpator 用wireshark过滤条件
udp and ip.addr == 10.8.0.2 and udp.port == 4672
如果是从windows端
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
// Validate command-line arguments
if (argc != 4) {
printf("Usage: %s <server_ip> <server_port> <message>\n", argv[0]);
return 1;
}
const char* server_ip = argv[1];
int server_port = atoi(argv[2]);
const char* message = argv[3];
// Initialize Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("WSAStartup failed. Error Code : %d", WSAGetLastError());
return 1;
}
// Create socket
SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd == INVALID_SOCKET) {
printf("Socket creation failed. Error Code : %d", WSAGetLastError());
WSACleanup();
return 1;
}
// Server address structure
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(server_port);
inet_pton(AF_INET, server_ip, &serverAddr.sin_addr);
// Send UDP packet
int bytesSent = sendto(sockfd, message, strlen(message), 0, (sockaddr*)&serverAddr, sizeof(serverAddr));
if (bytesSent == SOCKET_ERROR) {
printf("Send failed. Error Code : %d", WSAGetLastError());
closesocket(sockfd);
WSACleanup();
return 1;
}
printf("UDP packet sent.\n");
// Close socket
closesocket(sockfd);
WSACleanup();
return 0;
}
udp_sender.exe 47.93.27.106 14672 "Test UDP Packet"
服务端: sudo tcpdump -i any udp port 14672 -XX
这样,借助Open***, iptables & firewalld 在没有公网IP的条件下把本机TCP 4662 映射到远程云主机 TCP 14662, 把本机UDP 4672映射到远程云主机UDP 14672。花生壳 就赚不到我们的钱了。