当前位置:   article > 正文

firewalld防火墙转发流量到其他端口forward port rules_firewall 端口转发

firewall 端口转发

假设云主机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防火墙端口转发

  1. sudo sysctl -w net.ipv4.ip_forward=1
  2. sudo sh -c 'echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf'

 配置NAT确保public zone的流量转到en0:

  1. sudo iptables -t nat -A PREROUTING -p tcp --dport 14662 -j DNAT --to-destination 10.8.0.2:4662
  2. sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

确保iptables-serverices软件包安装了 

sudo yum install iptables-services

保存、重启iptables,让配置生效

  1. sudo service iptables save
  2. sudo systemctl restart iptables
  3. sudo systemctl enable iptables

重启防火墙firewalld

  1. sudo firewall-cmd --reload
  2. sudo systemctl restart firewalld

 查看改动的配置

  1. sudo firewall-cmd --list-all --zone=public
  2. sudo iptables -L -t nat

在这台VPS上 telnet 10.8.0.2 4662

windows客户端先连接上Open***, 另一台vps

当然也可以用在线工具open-ports, TCP可以支持, UDP还是要自己写个简单的代码测试。

windows客户端

同理udp 4672

  1. sudo firewall-cmd --zone=public --add-forward-port=port=14672:proto=udp:toport=4672:toaddr=10.8.0.2
  2. sudo firewall-cmd --zone=public --add-forward-port=port=14672:proto=udp:toport=4672:toaddr=10.8.0.2 --permanent
  3. sudo firewall-cmd --reload
  1. sudo iptables -t nat -A PREROUTING -p udp --dport 14672 -j DNAT --to-destination 10.8.0.2:4672
  2. sudo service iptables save
sudo systemctl restart firewalld

 发送UDP报文

echo -n "Test UDP Packet" | nc -u 47.93.27.106 14672 # 以下C代码同理 

udp_sender.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <arpa/inet.h>
  5. #include <sys/socket.h>
  6. #include <unistd.h>
  7. int main(int argc, char *argv[]) {
  8. if (argc != 4) {
  9. fprintf(stderr, "Usage: %s <server_ip> <server_port> <message>\n", argv[0]);
  10. exit(EXIT_FAILURE);
  11. }
  12. const char *server_ip = argv[1];
  13. int server_port = atoi(argv[2]);
  14. const char *message = argv[3];
  15. int sockfd;
  16. struct sockaddr_in server_addr;
  17. // Create socket
  18. if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  19. perror("Socket creation failed");
  20. exit(EXIT_FAILURE);
  21. }
  22. memset(&server_addr, 0, sizeof(server_addr));
  23. // Fill server information
  24. server_addr.sin_family = AF_INET;
  25. server_addr.sin_port = htons(server_port);
  26. server_addr.sin_addr.s_addr = inet_addr(server_ip);
  27. // Send UDP packet
  28. if (sendto(sockfd, message, strlen(message), 0, (const struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
  29. perror("Send failed");
  30. close(sockfd);
  31. exit(EXIT_FAILURE);
  32. }
  33. printf("UDP packet sent.\n");
  34. // Receive echoed packet
  35. char recvBuffer[512];
  36. struct sockaddr_in fromAddr;
  37. socklen_t fromAddrLen = sizeof(fromAddr);
  38. int bytesReceived = recvfrom(sockfd, recvBuffer, 512, 0, (struct sockaddr*)&fromAddr, &fromAddrLen);
  39. if (bytesReceived < 0) {
  40. perror("Receive failed");
  41. close(sockfd);
  42. exit(EXIT_FAILURE);
  43. }
  44. // Null-terminate the received data
  45. recvBuffer[bytesReceived] = '\0';
  46. // Print received message
  47. printf("Received echoed UDP packet: %s\n", recvBuffer);
  48. // Close socket
  49. close(sockfd);
  50. return 0;
  51. }

可以把本地eMule先停掉,防止UDP 4672端口被占用

UDPEchoServer.java
  1. package org.example;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.ActionEvent;
  5. import java.awt.event.ActionListener;
  6. import java.net.DatagramPacket;
  7. import java.net.DatagramSocket;
  8. import java.net.InetAddress;
  9. public class UDPEchoServer extends JFrame {
  10. private JTextField portField;
  11. private JButton startButton;
  12. private JTextArea messageArea;
  13. private DatagramSocket socket;
  14. private boolean running;
  15. public UDPEchoServer() {
  16. setTitle("UDP Echo Server");
  17. setSize(400, 300);
  18. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  19. setLocationRelativeTo(null);
  20. JPanel panel = new JPanel(new BorderLayout());
  21. portField = new JTextField();
  22. startButton = new JButton("Start Server");
  23. messageArea = new JTextArea();
  24. messageArea.setEditable(false);
  25. JPanel topPanel = new JPanel(new BorderLayout());
  26. topPanel.add(new JLabel("Port:"), BorderLayout.WEST);
  27. topPanel.add(portField, BorderLayout.CENTER);
  28. topPanel.add(startButton, BorderLayout.EAST);
  29. panel.add(topPanel, BorderLayout.NORTH);
  30. panel.add(new JScrollPane(messageArea), BorderLayout.CENTER);
  31. add(panel);
  32. startButton.addActionListener(new ActionListener() {
  33. @Override
  34. public void actionPerformed(ActionEvent e) {
  35. if (!running) {
  36. int port;
  37. try {
  38. port = Integer.parseInt(portField.getText());
  39. } catch (NumberFormatException ex) {
  40. JOptionPane.showMessageDialog(UDPEchoServer.this, "Invalid port number", "Error", JOptionPane.ERROR_MESSAGE);
  41. return;
  42. }
  43. startServer(port);
  44. } else {
  45. stopServer();
  46. }
  47. }
  48. });
  49. }
  50. private void startServer(int port) {
  51. try {
  52. socket = new DatagramSocket(port);
  53. running = true;
  54. startButton.setText("Stop Server");
  55. portField.setEditable(false);
  56. messageArea.append("Server started on port " + port + "\n");
  57. Thread serverThread = new Thread(new Runnable() {
  58. @Override
  59. public void run() {
  60. byte[] buffer = new byte[1024];
  61. while (running) {
  62. try {
  63. DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
  64. socket.receive(packet);
  65. String received = new String(packet.getData(), 0, packet.getLength());
  66. InetAddress address = packet.getAddress();
  67. int clientPort = packet.getPort();
  68. messageArea.append("Received: " + received + " from " + address + ":" + clientPort + "\n");
  69. // Echo the message back
  70. DatagramPacket response = new DatagramPacket(packet.getData(), packet.getLength(), address, clientPort);
  71. socket.send(response);
  72. messageArea.append("Echoed: " + received + " to " + address + ":" + clientPort + "\n");
  73. } catch (Exception ex) {
  74. if (running) {
  75. messageArea.append("Error: " + ex.getMessage() + "\n");
  76. }
  77. }
  78. }
  79. }
  80. });
  81. serverThread.start();
  82. } catch (Exception ex) {
  83. messageArea.append("Error starting server: " + ex.getMessage() + "\n");
  84. }
  85. }
  86. private void stopServer() {
  87. running = false;
  88. socket.close();
  89. startButton.setText("Start Server");
  90. portField.setEditable(true);
  91. messageArea.append("Server stopped\n");
  92. }
  93. public static void main(String[] args) {
  94. SwingUtilities.invokeLater(new Runnable() {
  95. @Override
  96. public void run() {
  97. new UDPEchoServer().setVisible(true);
  98. }
  99. });
  100. }
  101. }

 本地启动Java UDP Echo server测试UDP port number 4672连通性

云主机VPS发到本地Windows:

确认从云主机14672端口的UDP流量转发到windows本机的UDP 4672服务,检查UDP Echo server

确认接收到的内容与远程主机发过来的一样。

当然如果本机eMule已经启动了,端口已被占用,则需要用wireshark看

打开wireshark找到tunnel adaptor 用wireshark过滤条件 

 udp and ip.addr == 10.8.0.2 and udp.port == 4672

如果是从windows端

  1. #include <WinSock2.h>
  2. #include <WS2tcpip.h>
  3. #include <stdio.h>
  4. #pragma comment(lib, "Ws2_32.lib")
  5. int main(int argc, char* argv[]) {
  6. // Validate command-line arguments
  7. if (argc != 4) {
  8. printf("Usage: %s <server_ip> <server_port> <message>\n", argv[0]);
  9. return 1;
  10. }
  11. const char* server_ip = argv[1];
  12. int server_port = atoi(argv[2]);
  13. const char* message = argv[3];
  14. // Initialize Winsock
  15. WSADATA wsaData;
  16. if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
  17. printf("WSAStartup failed. Error Code : %d", WSAGetLastError());
  18. return 1;
  19. }
  20. // Create socket
  21. SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  22. if (sockfd == INVALID_SOCKET) {
  23. printf("Socket creation failed. Error Code : %d", WSAGetLastError());
  24. WSACleanup();
  25. return 1;
  26. }
  27. // Server address structure
  28. sockaddr_in serverAddr;
  29. serverAddr.sin_family = AF_INET;
  30. serverAddr.sin_port = htons(server_port);
  31. inet_pton(AF_INET, server_ip, &serverAddr.sin_addr);
  32. // Send UDP packet
  33. int bytesSent = sendto(sockfd, message, strlen(message), 0, (sockaddr*)&serverAddr, sizeof(serverAddr));
  34. if (bytesSent == SOCKET_ERROR) {
  35. printf("Send failed. Error Code : %d", WSAGetLastError());
  36. closesocket(sockfd);
  37. WSACleanup();
  38. return 1;
  39. }
  40. printf("UDP packet sent.\n");
  41. // Receive echoed packet
  42. char recvBuffer[512];
  43. sockaddr_in fromAddr;
  44. int fromAddrLen = sizeof(fromAddr);
  45. int bytesReceived = recvfrom(sockfd, recvBuffer, 512, 0, (sockaddr*)&fromAddr, &fromAddrLen);
  46. if (bytesReceived == SOCKET_ERROR) {
  47. printf("Receive failed. Error Code : %d", WSAGetLastError());
  48. closesocket(sockfd);
  49. WSACleanup();
  50. return 1;
  51. }
  52. // Null-terminate the received data
  53. recvBuffer[bytesReceived] = '\0';
  54. // Print received message
  55. printf("Received echoed UDP packet: %s\n", recvBuffer);
  56. // Close socket
  57. closesocket(sockfd);
  58. WSACleanup();
  59. return 0;
  60. }

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。花生壳 就赚不到我们的钱了。

TCP端口连通性测试
 

windows UDP Echo server:

  1. #include <iostream>
  2. #include <winsock2.h>
  3. #include <ws2tcpip.h>
  4. #include <windows.h>
  5. #pragma comment(lib, "Ws2_32.lib")
  6. #define BUFFER_SIZE 1024
  7. int main() {
  8. WSADATA wsaData;
  9. SOCKET serverSocket = INVALID_SOCKET;
  10. sockaddr_in serverAddr, clientAddr;
  11. int clientAddrSize = sizeof(clientAddr);
  12. char buffer[BUFFER_SIZE];
  13. // Initialize Winsock
  14. if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
  15. std::wcerr << L"WSAStartup failed with error: " << WSAGetLastError() << std::endl;
  16. return 1;
  17. }
  18. // Create a socket for the server
  19. serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  20. if (serverSocket == INVALID_SOCKET) {
  21. std::wcerr << L"Socket creation failed with error: " << WSAGetLastError() << std::endl;
  22. WSACleanup();
  23. return 1;
  24. }
  25. int port;
  26. std::wcout << L"Enter port number: ";
  27. std::wcin >> port;
  28. // Setup the UDP server address structure
  29. memset(&serverAddr, 0, sizeof(serverAddr));
  30. serverAddr.sin_family = AF_INET;
  31. serverAddr.sin_addr.s_addr = INADDR_ANY;
  32. serverAddr.sin_port = htons(port);
  33. // Bind the socket to the port
  34. if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
  35. std::wcerr << L"Bind failed with error: " << WSAGetLastError() << std::endl;
  36. closesocket(serverSocket);
  37. WSACleanup();
  38. return 1;
  39. }
  40. std::wcout << L"UDP Echo Server started on port " << port << std::endl;
  41. while (true) {
  42. // Receive a message from a client
  43. int bytesReceived = recvfrom(serverSocket, buffer, BUFFER_SIZE - 1, 0, (sockaddr*)&clientAddr, &clientAddrSize);
  44. if (bytesReceived == SOCKET_ERROR) {
  45. std::wcerr << L"recvfrom failed with error: " << WSAGetLastError() << std::endl;
  46. break;
  47. }
  48. // Null-terminate the received data
  49. buffer[bytesReceived] = '\0';
  50. // Echo the message back to the client
  51. int bytesSent = sendto(serverSocket, buffer, bytesReceived, 0, (sockaddr*)&clientAddr, clientAddrSize);
  52. if (bytesSent == SOCKET_ERROR) {
  53. std::wcerr << L"sendto failed with error: " << WSAGetLastError() << std::endl;
  54. break;
  55. }
  56. // Display received message and echo status
  57. WCHAR clientIp[INET_ADDRSTRLEN];
  58. InetNtop(AF_INET, &clientAddr.sin_addr, clientIp, INET_ADDRSTRLEN);
  59. std::wcout << L"Received: " << buffer << L" from " << clientIp << L":" << ntohs(clientAddr.sin_port) << std::endl;
  60. std::wcout << L"Echoed: " << buffer << L" to " << clientIp << L":" << ntohs(clientAddr.sin_port) << std::endl;
  61. }
  62. // Cleanup
  63. closesocket(serverSocket);
  64. WSACleanup();
  65. return 0;
  66. }

$ ~/bin/udp_sender 云主机的公网IP 14672 "Test UDP Echo Server"
UDP packet sent.
Received echoed UDP packet: Test UDP Echo Server

如果防火墙有重复的配置,需要删除

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/1002577
推荐阅读
相关标签
  

闽ICP备14008679号