领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

Windows端口转发小工具(window 端口转发)

nixiaole 2024-11-15 23:01:49 知识剖析 21 ℃

先上样例



创建Maven项目

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.wpf</groupId>
    <artifactId>WindowsPortForward</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>WindowsPortForward</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.25</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5</version>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>org.wpf.App</mainClass>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>.</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <descriptors>
                                <descriptor>src/assembly/assembly.xml</descriptor>
                            </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

assembly.xml

可以把依赖代码打包到一起;存放位置:src/assembly/assembly.xml

<assembly>
    <id>jar-with-dependencies</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <!-- 默认的配置 -->
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
        </dependencySet>
        <!-- 增加scope类型为system的配置 -->
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>system</scope>
        </dependencySet>
    </dependencySets>
</assembly>

Javafx 启动类

package org.wpf;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;


/**
 * lucy
 *
 */
public class App extends Application {

    private final ObservableList<WPF> data = FXCollections.observableArrayList();
    private static final Set<Integer> ports= new HashSet<>();

    public static void main( String[] args ) {
        launch(args);
    }

    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Label agentPortLabel = new Label("代理端口:");
        agentPortLabel.setStyle("-fx-font-family: '宋体'; -fx-font-weight: bold;");
        AnchorPane.setTopAnchor(agentPortLabel,10.0);
        AnchorPane.setLeftAnchor(agentPortLabel,10.0);

        TextField agentPortTextField = new TextField();
        agentPortTextField.setPrefWidth(65.0);
        AnchorPane.setTopAnchor(agentPortTextField,7.0);
        AnchorPane.setLeftAnchor(agentPortTextField,70.0);
        agentPortTextField.setPromptText("1~65535");
        agentPortTextField.setAlignment(Pos.BASELINE_LEFT);

        Label targetIPLabel = new Label("目标IP:");
        targetIPLabel.setStyle("-fx-font-family: '宋体'; -fx-font-weight: bold;");
        AnchorPane.setTopAnchor(targetIPLabel,10.0);
        AnchorPane.setLeftAnchor(targetIPLabel,140.0);


        TextField agentIPTextField = new TextField();
        agentIPTextField.setPrefWidth(140.0);
        AnchorPane.setTopAnchor(agentIPTextField,7.0);
        AnchorPane.setLeftAnchor(agentIPTextField,185.0);
        agentIPTextField.setPromptText("ipv4");
        agentIPTextField.setAlignment(Pos.BASELINE_LEFT);


        Label targetPortLabel = new Label("目标端口:");
        targetPortLabel.setStyle("-fx-font-family: '宋体'; -fx-font-weight: bold;");
        AnchorPane.setTopAnchor(targetPortLabel,10.0);
        AnchorPane.setLeftAnchor(targetPortLabel,330.0);

        TextField targetPortTextField = new TextField();
        targetPortTextField.setPrefWidth(65.0);
        AnchorPane.setTopAnchor(targetPortTextField,7.0);
        AnchorPane.setLeftAnchor(targetPortTextField,390.0);
        targetPortTextField.setPromptText("1~65535");
        targetPortTextField.setAlignment(Pos.BASELINE_LEFT);

        Button button = new Button("端口转发");
        button.setStyle("-fx-background-color: #3378d2;-fx-text-fill: white; -fx-font-size: 12px;");
        AnchorPane.setTopAnchor(button,6.0);
        AnchorPane.setLeftAnchor(button,480.0);
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                String  agentPort = agentPortTextField.getText();
                String targetPort = targetPortTextField.getText();
                String agentIP = agentIPTextField.getText();
                if(StrUtil.isEmpty(agentPort)||!Validator.isNumber(agentPort)||Convert.toInt(agentPort)>65535||Convert.toInt(agentPort)<=0){
                    Alert alert = new Alert(Alert.AlertType.ERROR, "请输入正确的代理端口,端口范围[1~65535]");
                    alert.showAndWait();
                    return;
                }
                if(StrUtil.isEmpty(targetPort)||!Validator.isNumber(targetPort)||Convert.toInt(targetPort)>65535||Convert.toInt(targetPort)<=0){
                    Alert alert = new Alert(Alert.AlertType.ERROR, "请输入正确的目标端口,端口范围[1~65535]");
                    alert.showAndWait();
                    return;
                }
                if(!Validator.isIpv4(agentIP)){
                    Alert alert = new Alert(Alert.AlertType.ERROR, "请输入正确的IPV4地址");
                    alert.showAndWait();
                    return;
                }

                if(ports.contains(Convert.toInt(agentPort))){
                    Alert alert = new Alert(Alert.AlertType.ERROR, "当前端口已经被代理,请更换其他端口");
                    alert.showAndWait();
                    return;
                }
                ports.add(Convert.toInt(agentPort));
                start(Convert.toInt(agentPort), agentIP,Convert.toInt(targetPort));
                WPF wpf = new WPF(Convert.toInt(agentPort), Convert.toInt(targetPort), agentIP);
                data.add(wpf);
            }
        });

        Line line = new Line(0,40,9999,0);
        line.setStroke(Color.GRAY);

        TableView<WPF> table = new TableView<WPF>();
        table.setItems(data);
        TableColumn<WPF, Integer> agentPortCol = new TableColumn<WPF, Integer>("代理端口");
        agentPortCol.setCellValueFactory(new PropertyValueFactory<>("sourcePort"));
        agentPortCol.setStyle("-fx-font-size: 14px;");

        TableColumn<WPF, String> targetIPCol = new TableColumn<WPF, String>("目标IP");
        targetIPCol.setPrefWidth(240);
        targetIPCol.setCellValueFactory(new PropertyValueFactory<>("targetIP"));
        targetIPCol.setStyle("-fx-font-size: 14px;");

        TableColumn<WPF, String> targetPortCol = new TableColumn<WPF, String>("目标端口");
        targetPortCol.setCellValueFactory(new PropertyValueFactory<>("targetPort"));
        targetPortCol.setStyle("-fx-font-size: 14px;");

        TableColumn<WPF, Void> statusCol = new TableColumn<WPF, Void>("启用/停用");
        statusCol.setPrefWidth(110);
        statusCol.setCellFactory(param -> new TableCellWithToggleButton(row -> {

        }));
        TableColumn<WPF, Void> operationCol = new TableColumn<WPF, Void>("操作");
        operationCol.setPrefWidth(110);
        operationCol.setCellFactory(param -> new TableCellWithButton( row -> {
            int sourcePort = row.getSourcePort();
            String targetIP = row.getTargetIP();
            int targetPort = row.getTargetPort();
            stop(sourcePort,targetIP,targetPort);
            ports.remove(sourcePort);
            data.remove(row);
        }));

        table.getColumns().addAll(agentPortCol,targetIPCol,targetPortCol,statusCol,operationCol);
        AnchorPane.setTopAnchor(table,50.0);
        AnchorPane.setLeftAnchor(table,5.0);
        AnchorPane.setRightAnchor(table,5.0);

        root.getChildren().addAll(agentPortLabel,agentPortTextField,targetIPLabel,agentIPTextField,targetPortLabel,targetPortTextField,button,line,table);
        Scene scene = new Scene(root,600,300);
        primaryStage.getIcons().add(new Image("/logo.png"));//设置图标
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void start(int sourcePort,String targetIP,int targetPort){
        String[] command = {"cmd.exe", "/c", "netsh", "interface", "portproxy", "add", "v4tov4", "listenport="+sourcePort, "listenaddress=127.0.0.1", "connectport="+targetPort, "connectaddress="+targetIP};
        try{
            // 使用管理员权限执行命令
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            // 获取命令执行结果
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            // 等待命令执行完成
            int exitCode = process.waitFor();
            System.out.println("Command executed with exit code: " + exitCode);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void init(){
        String[] command = {"cmd.exe", "/c", "netsh", "interface", "portproxy", "show", "all"};
        try{
            // 使用管理员权限执行命令
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            // 获取命令执行结果
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            String line;
            while ((line = reader.readLine()) != null) {
                if(line.startsWith("127.0.0.1")){
                    List<String> slist = removeEmptyElements(StrUtil.split(line, " "));
                    WPF wpf = new WPF(Convert.toInt(slist.get(1)), Convert.toInt(slist.get(3)), slist.get(2));
                    data.add(wpf);
                    ports.add(Convert.toInt(slist.get(1)));
                }
            }
            // 等待命令执行完成
            int exitCode = process.waitFor();
            System.out.println("Command executed with exit code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static  List<String> removeEmptyElements(List<String> slist){
        List<String> tlist = new ArrayList<>();
        for (String str : slist) {
            if (!str.isEmpty()) {
                tlist.add(str.trim());
            }
        }
        return tlist;
    }
    public static void stop(int sourcePort,String targetIP,int targetPort){
        String[] command = {"cmd.exe", "/c", "netsh", "interface", "portproxy", "delete", "v4tov4", "listenport="+sourcePort, "listenaddress=127.0.0.1"};
        try{
            // 使用管理员权限执行命令
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            // 获取命令执行结果
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            // 等待命令执行完成
            int exitCode = process.waitFor();
            System.out.println("Command executed with exit code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static class TableCellWithButton extends TableCell<WPF, Void> {
        private final Button button;

        public TableCellWithButton(ButtonClickedAction action) {
            this.button = new Button();

            button.setStyle("-fx-pref-width:20px; -fx-pref-height: 8px; -fx-background-color: red; -fx-shape: 'M909.5 242.1H147.6c-13.3 0-24.1-10.9-24.1-24.1v-8.4c0-13.3 10.9-24.1 24.1-24.1h761.9c13.3 0 24.1 10.9 24.1 24.1v8.4c0 13.2-10.8 24.1-24.1 24.1zM701.8 870H351.9c-71 0-128.8-57.8-128.8-128.8V213.7h51.5v527.5c0 42.6 34.7 77.3 77.3 77.3h349.9c42.6 0 77.3-34.7 77.3-77.3V213.7h51.5v527.5c0 71-57.8 128.8-128.8 128.8zM647.7 186h-51.5c0-28.4-29.9-51.6-66.7-51.6-36.7 0-66.6 23.1-66.6 51.6h-51.5c0-56.9 53-103.1 118.1-103.1S647.7 129.1 647.7 186zM384.2 708.5h-2.9c-13.4 0-24.3-10.9-24.3-24.3V373.8c0-13.4 10.9-24.3 24.3-24.3h2.9c13.4 0 24.3 10.9 24.3 24.3v310.4c0 13.3-10.9 24.3-24.3 24.3zM531 708.5h-2.9c-13.4 0-24.3-10.9-24.3-24.3V373.8c0-13.4 10.9-24.3 24.3-24.3h2.9c13.4 0 24.3 10.9 24.3 24.3v310.4c0 13.3-10.9 24.3-24.3 24.3zM677.8 708.5h-2.9c-13.4 0-24.3-10.9-24.3-24.3V373.8c0-13.4 10.9-24.3 24.3-24.3h2.9c13.4 0 24.3 10.9 24.3 24.3v310.4c0 13.3-11 24.3-24.3 24.3z'");
            this.button.setOnAction(event -> {
                action.handle(getTableView().getItems().get(getIndex()));
            });
        }

        @Override
        protected void updateItem(Void item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
            } else {
                setGraphic(button);
            }
            setAlignment(Pos.CENTER);
        }
    }

    public static class TableCellWithToggleButton extends TableCell<WPF, Void> {
        private final ToggleButton button;

        public TableCellWithToggleButton(ButtonClickedAction action) {
            this.button = new ToggleButton();
            button.setStyle("-fx-pref-width:45px; -fx-pref-height: 10px; -fx-background-color:#33d260; -fx-shape: 'M366 294.504c-132 0-240 107.104-240 238s108 238 240 238h304c132 0 240-107.104 240-238s-108-238-240-238h-304z m308 442.16c-111.28 0-201.504-91.408-201.504-204.168s90.224-204.16 201.504-204.16 201.504 91.408 201.504 204.168-90.224 204.16-201.504 204.16z'");
            // 设置按钮初始状态
            button.setSelected(true); // 初始状态为未选中
           this.button.setOnAction(event -> {
               WPF wpf = getTableView().getItems().get(getIndex());
               if (button.isSelected()) {
                   //按钮状态:开
                   button.setStyle("-fx-pref-width:45px; -fx-pref-height: 10px; -fx-background-color:#33d260; -fx-shape: 'M366 294.504c-132 0-240 107.104-240 238s108 238 240 238h304c132 0 240-107.104 240-238s-108-238-240-238h-304z m308 442.16c-111.28 0-201.504-91.408-201.504-204.168s90.224-204.16 201.504-204.16 201.504 91.408 201.504 204.168-90.224 204.16-201.504 204.16z'");
                   App.start(wpf.getSourcePort(),wpf.getTargetIP(),wpf.getTargetPort());
                   ports.add(wpf.getSourcePort());
               } else {
                   //按钮状态:关
                   button.setStyle(" -fx-pref-width:45px; -fx-pref-height: 10px; -fx-shape: 'M2 512c0-141 114-255 255-255h510c141 0 255 114 255 255S908 767 767 767H257C116 767 2 653 2 512z m255 208.8c115.5 0 208.8-93.2 208.8-208.8S372.5 303.2 257 303.2c-115.5 0-208.8 93.2-208.8 208.8S141.5 720.8 257 720.8z'");
                    App.stop(wpf.getSourcePort(),wpf.getTargetIP(),wpf.getTargetPort());
               }
               action.handle(wpf);
            });
        }

        @Override
        protected void updateItem(Void item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
            } else {
                setGraphic(button);
            }
            setAlignment(Pos.CENTER);
        }
    }

    @FunctionalInterface
    public interface ButtonClickedAction {
        void handle(WPF person);
    }


    public static class WPF{
        private int sourcePort;
        private int targetPort;
        private String targetIP;

        public WPF(int sourcePort, int targetPort, String targetIP) {
            this.sourcePort = sourcePort;
            this.targetPort = targetPort;
            this.targetIP = targetIP;
        }

        public int getSourcePort() {
            return sourcePort;
        }

        public void setSourcePort(int sourcePort) {
            this.sourcePort = sourcePort;
        }

        public int getTargetPort() {
            return targetPort;
        }

        public void setTargetPort(int targetPort) {
            this.targetPort = targetPort;
        }

        public String getTargetIP() {
            return targetIP;
        }

        public void setTargetIP(String targetIP) {
            this.targetIP = targetIP;
        }
    }
}

资源文件

resource目录下存放logo.png,网上随便找到。别投诉我侵权哦。



打包启动

java -jar WindowsPortForward-1.0.0-jar-with-dependencies.jar

注意

使用管理员身份启动cmd,并运行启动命令。

转发一个端口测试下


Tags:

最近发表
标签列表