directory

1. Port scanning technology

2. Single-threaded Socket connection

Scan based on TCP Connect port

Multithreaded TCP connection scanning

Five, small program complete source code

1. Port scanning technology

As we all know, every machine in the network has an IP address, and the IP address is closely related to the host port, by the way, do you know the range of the port number?

That’s right, 0 to 65535. In computer networks, two bytes are used to represent a port number as a 16-bit binary number. What ports does a host have open for these ports?

For example, port 80,443 corresponds to HTTP and HTTPS services, port 23 corresponds to Telnet remote management, port 25 corresponds to SMTP services, and so on. Let’s implement a simple port scan applet.

Scanning for open ports on a host is a common operation: attack (searching for open ports on the destination host) and defense (detecting abnormal open ports on the host). Basic port scanning techniques can be used:

  • Create Socket connection: new Socket(IP,port)
  • TCP Connect detection

This article applies to the computer network, Java development, Socket programming and multithreaded entry partner! Can be combined with a “Java development host IP scan artifact”, further detection network attack and defense useful information!

2. Single-threaded Socket connection

Now start the simple development process of small programs, starting with a single thread and moving forward step by step.

Socket socket=new Socket(host,port);
Copy the code

In this case, we create a Socket connection. The principle of this method is to establish a connection with the target IP address and listen on the port. If the time exceeds, the port is not open and the connection cannot be successful.

An IOException is thrown when the connection fails, so you can determine if the port is closed when the exception is thrown.

The specific implementation is very simple, we scan the port operation into a thread, does not affect the main program running, and then given a range of ports such as 0 to 100, one by one Socket connection, so that you can know which port open.

try { Socket socket=new Socket(host,port); socket.close(); Platform.runlater (() -> {result.appendtext (" port "+port+" is open.\n"); }); } catch (IOException e) {result.appendtext (" port "+port+" is closed.\n"); }Copy the code

This is the result of a partial port scan on my host.

Here’s a GIF to see what’s going on.

Scan based on TCP Connect port

From the dynamic graph scanning process can be found that this speed is obviously not tolerable, just like a page loading half a day has not been shown, so, in order to better user experience, on the basis of optimization and improvement, the most important thing is the scanning speed!

The previous method takes too long to wait when a port shutdown is encountered and the time cost is too high. Start using another method, port scanning based on TCP Connect.

Socket socket=new Socket();
socket.connect(new InetSocketAddress(host,port),200);
socket.close();
Copy the code

Instead of establishing a connection to each IP and port, you use the “probe” method, using the InetSocketAddress class, with a timeout of 200ms, which is obviously several times faster!

The code implementation is very simple, and that’s it

try { Socket socket=new Socket(); socket.connect(new InetSocketAddress(host,port),200); socket.close(); Platform.runlater (() -> {result.appendtext (" port "+port+" is open.\n"); }); } catch (IOException e) {result.appendtext (" port "+port+" is closed.\n"); }Copy the code

The optimized and improved comparison scanning speed is shown in the following GIF:

In contrast, the scanning speed is greatly improved!

At this point, the speed increase is relative. For example, scan 1000 ports and you know how slow it is, but you can’t wait!

Less than 80 ports scanned in 20 seconds! A rough calculation would take at least 4 minutes for 1000 ports, which is unacceptable!

Multithreaded TCP connection scanning

At this time, can only use the back hand, multi-threaded special… Hey hey

Our little goal right now is to be fast, and multithreading is great. Here I’m going to start 100 threads to do this scan.

for (int i=0; i<100; i++) { readThread=new Thread(new ScanHandler(i, 100),"scanThread"); readThread.start(); }Copy the code

At the same time, we need to pay attention to thread safety when we start multi-threading. In this task, we also need to pay attention to the port range of each thread to avoid repeated scanning and scan end judgment.

Using atomic variables to ensure thread safety, counting correctly solves the above problems.

static AtomicInteger portCount portCount=new AtomicInteger(0);
Copy the code

Define a scanning thread processing class ScanHandler, the processing logic is roughly: each thread has its own id, according to the id to determine its responsible port number, each thread maintains the atomic count of the scanned port.

class ScanHandler implements Runnable{ private int totalThreadNum; // Total number of threads used for port scanning. Default is 10 private int threadNo; Private int startP= integer.parseint (startPort.gettext ()); private int endP=Integer.parseInt(endPort.getText()); private String host = targetIP.getText().trim(); public ScanHandler(int threadNo) { this.totalThreadNum = 10; this.threadNo = threadNo; } public ScanHandler(int threadNo,int totalThreadNum) { this.totalThreadNum = totalThreadNum; this.threadNo = threadNo; } @override public void run() {for (int I =startP+threadNo; i<=endP; i=i+totalThreadNum){ int port=i; if (readThread.isInterrupted()){ readThread.interrupt(); break; } try { Socket socket=new Socket(); socket.connect(new InetSocketAddress(host,port),200); socket.close(); Platform.runlater (() -> {result.appendtext (" port "+port+" is open.\n"); }); }catch (IOException e){// result.appendtext (" port "+ I +" is closed.\n"); } portCount.incrementAndGet(); } the if (portCount. The get () = = (endP - startP + 1)) {/ / judge the scan portCount. IncrementAndGet (); Platform. RunLater (() - > {result. AppendText (" \ n -- -- -- -- -- -- -- -- -- -- -- -- -- multithreading scanning end -- -- -- -- -- -- -- -- -- -- -- -- -- \ n "); }); }}}Copy the code

Now look at how fast the multithreading is, it feels smooth, 1000 ports can be scanned in less than 10 seconds!

Does it feel pretty perfect, but according to common sense is always almost what, in fact, is a progress bar display, just like we download things, there is a progress bar and percentage looking at the bottom of the heart, arrangement!

Java has a progress class that can be used directly, namely the following line of code, and then added to the scan thread to update the progress in real time.

ProgressBar progressBar=new ProgressBar();
Copy the code

Let’s see what happens. Scan 5000 ports with the multithreaded version.

Five, small program complete source code

Complete source code, without reservation, suggested decisive collection, so as not to use later can not find!

/**
 * HostScannerFX.java
 * Copyright (c) 2021 Charzous
 * All right reserved.
 * @date 2021-06-07 下午 09:38
 */


import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicInteger;

public class PortScannerFX extends Application {
    private TextArea result = new TextArea();
    private TextField targetIP = new TextField();
    private TextField startPort = new TextField();
    private TextField endPort = new TextField();
    private Button scan = new Button("扫描");
    private Button quickScan = new Button("快速扫描");
    private Button threadScan = new Button("多线程扫描");
    private Button ex=new Button("退出");
    private Button stop=new Button("停止扫描");
    private Thread readThread;
    static AtomicInteger portCount;//用于统计已扫描的端口数量

    private ProgressBar progressBar=new ProgressBar();
    private Label bar=new Label("0%");

    @Override
    public void start(Stage primaryStage) throws Exception {
        BorderPane mainPane = new BorderPane();

        HBox barBox=new HBox();
        barBox.setSpacing(10);
        barBox.setPadding(new Insets(10, 0, 10, 0));
        progressBar.setPrefWidth(700);
        progressBar.setProgress(0);
        HBox.setHgrow(progressBar,Priority.ALWAYS);
        barBox.getChildren().addAll(bar,progressBar);

        VBox vBox = new VBox();
        vBox.setSpacing(10);
        vBox.setPadding(new Insets(10, 20, 10, 20));
//        vBox.setAlignment(Pos.CENTER);
        VBox.setVgrow(result, Priority.ALWAYS);
        vBox.getChildren().addAll(new Label("端口扫描结果:"), result,barBox);
        mainPane.setCenter(vBox);

        startPort.setPrefWidth(60);
        endPort.setPrefWidth(60);
        HBox hBox1 = new HBox();
        hBox1.setSpacing(10);
        hBox1.setPadding(new Insets(10, 20, 10, 20));
        hBox1.setAlignment(Pos.CENTER);
        hBox1.getChildren().addAll(new Label("目标主机ip:"), targetIP, new Label("起始端口号:"), startPort, new Label("结束端口号:"),endPort);

        HBox hBox2 = new HBox();
        hBox2.setSpacing(10);
        hBox2.setPadding(new Insets(10, 20, 10, 20));
        hBox2.setAlignment(Pos.CENTER);

        hBox2.getChildren().addAll(scan,quickScan,threadScan,stop,ex);

        VBox vBox1 = new VBox();
        vBox1.setSpacing(10);
        vBox1.setPadding(new Insets(10, 20, 10, 20));
        vBox1.setAlignment(Pos.CENTER);
        vBox1.getChildren().addAll(hBox1, hBox2);
        mainPane.setBottom(vBox1);

        Scene scene = new Scene(mainPane, 800, 500);
        primaryStage.setScene(scene);
        primaryStage.setTitle("PortScannerFX");
        primaryStage.show();



        //扫描
        scan.setOnAction(event -> {
            String host = targetIP.getText().trim();
            int sp = Integer.parseInt(startPort.getText());
            int ep=Integer.parseInt(endPort.getText());
            readThread = new Thread(() -> {

                double num=0.0;
                for (int i = sp; i <= ep; i++) {
                    int port=i;
                    if (readThread.isInterrupted()){
                        readThread.interrupt();
//                        Thread.interrupted();
                        break;
                    }
                    try {
                        Socket socket=new Socket(host,port);
                        socket.close();
                        Platform.runLater(() -> {
                                result.appendText("端口 " +port+ " is open.\n");
                        });
                    } catch (IOException e) {
                        result.appendText("端口 " +port+ " is closed.\n");
                    }
                    num++;
                    double finalNum = num;
                    Platform.runLater(()->{
                        progressBar.setProgress(finalNum/(ep-sp+1));//进度条
                        bar.setText(""+ Integer.valueOf((int) (finalNum /(ep-sp+1)*100))+"%");
                    });
                }
                result.appendText("端口扫描结束!\n");
            },"scanThread");
            readThread.start();

        });

        //快速扫描
        quickScan.setOnAction(event -> {
            String host = targetIP.getText().trim();
            int sp = Integer.parseInt(startPort.getText());
            int ep=Integer.parseInt(endPort.getText());
            readThread = new Thread(() -> {

                double num=0;
                for (int i = sp; i <= ep; i++) {
                    if (readThread.isInterrupted()){
                        readThread.interrupt();
//                        Thread.interrupted();
                        break;
                    }
                    int port=i;
                    try {
                        Socket socket=new Socket();
                        socket.connect(new InetSocketAddress(host,port),200);

                        socket.close();
                        Platform.runLater(() -> {
                            result.appendText("端口 " +port+ " is open.\n");
                        });
                    } catch (IOException e) {
                        result.appendText("端口 " +port+ " is closed.\n");
                    }
                    num++;
                    double finalNum = num;
                    Platform.runLater(()->{
                        progressBar.setProgress(finalNum/(ep-sp+1));//进度条
                        bar.setText(""+ Integer.valueOf((int) (finalNum /(ep-sp+1)*100))+"%");
                    });
                }
                result.appendText("端口扫描结束!\n");
            },"scanThread");
            readThread.start();
        });

        threadScan.setOnAction(event -> {
            portCount=new AtomicInteger(0);
            int sp = Integer.parseInt(startPort.getText());
            int ep=Integer.parseInt(endPort.getText());
            for (int i=0;i<100;i++) {
                readThread=new Thread(new ScanHandler(i, 100),"scanThread");
                readThread.start();
            }
        });

        stop.setOnAction(event -> {
            interrupt("scanThread");
        });

        //退出
        ex.setOnAction(event -> {
            exit();
        });
        primaryStage.setOnCloseRequest(event -> {
            exit();
        });
    }

    public void interrupt(String threadName){
        ThreadGroup currentGroup=Thread.currentThread().getThreadGroup();
        int noThreads=currentGroup.activeCount();
        Thread[] lstThreads=new Thread[noThreads];
        currentGroup.enumerate(lstThreads);
        for (int i=0;i<noThreads;i++){
            if (lstThreads[i].getName().equals(threadName))
                lstThreads[i].interrupt();
        }
    }

    public void exit(){
        System.exit(0);
    }



    class ScanHandler implements Runnable{
        private int totalThreadNum;//用于端口扫描的总共线程数量,默认为10
        private int threadNo;//线程号,表示第几个线程
        private int startP=Integer.parseInt(startPort.getText());
        private int endP=Integer.parseInt(endPort.getText());
        private String host = targetIP.getText().trim();

        public ScanHandler(int threadNo) {
            this.totalThreadNum = 10;
            this.threadNo = threadNo;
        }

        public ScanHandler(int threadNo,int totalThreadNum) {
            this.totalThreadNum = totalThreadNum;
            this.threadNo = threadNo;
        }

        @Override
        public void run() {
            //startPort和endPort为成员变量,表示需要扫描的起止端口
            for (int i=startP+threadNo;i<=endP;i=i+totalThreadNum){
                int port=i;
                if (readThread.isInterrupted()){
                    readThread.interrupt();
                    break;
                }
                try {
                    Socket socket=new Socket();
                    socket.connect(new InetSocketAddress(host,port),200);
                    socket.close();
                    Platform.runLater(() -> {
                        result.appendText("端口 " +port+ " is open.\n");
                    });
                }catch (IOException e){
//                    result.appendText("端口 " +i+ " is closed.\n");
                }
                portCount.incrementAndGet();
                Platform.runLater(()->{
                    bar.setText(""+ Integer.valueOf((int) ((portCount.doubleValue())/(endP-startP+1)*100))+"%");//进度比
                    progressBar.setProgress((portCount.doubleValue())/(endP-startP+1));//进度条
                });
            }
            if (portCount.get()==(endP-startP+1)){//判断扫描结束
                portCount.incrementAndGet();
                Platform.runLater(()->{
                    result.appendText("\n-------------多线程扫描结束-------------\n");
                });
            }
        }
    }


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

Complete source code, without reservation, suggest decisive collection, so as not to use later can not find, quickly begin to develop a simple port scan small program!

Today with Java development technology: Socket programming port scan small program, zero basic Socket programming detailed tutorial, this content is not simple, interesting, harvest? Welcome to exchange and study!

The last thing I want to tell you is, what is the knowledge necessary to learn Java? A lot of fans private message my Java learning route, I recommend this knowledge map, fans all think the quality is very good!

Learning Java development, Socket network programming and other knowledge, there are many interesting small programs can be done, recently I also follow this set of “Java engineer learning growth knowledge map” for system learning, CSDN is officially launched, the quality is very good!

Which contains the Java professional architecture complete and detailed, recommended to everyone to learn to use, interested can scan code to view, recently I also in the study, of course, my article will record learning, welcome to read, such as my column “Socket network programming”, “Java treasure”.

Unfold is such, size 870mm*560mm typesetting good-looking, content is very substantial. Recommended to the partners in need, together to learn Java development!

** If you feel good, welcome to “one key three” oh, click like to collect attention, comment questions and suggestions, welcome to exchange and learn! Let’s make progress together. See you in the next chapter! More details can be found on my CSDN blog! 支那

This content starting my CSDN blog: csdn-czh.blog.csdn.net/article/det…