Port Scanner Dengan Python
Tags: python
Published: 2020-10-24 15:54:06

Port Scanners biasanya digunakan untuk Penetration Testing dan Information Gathering. Pada dasarnya, hal itu adalah mencari port terbuka di host karena ada satu dari dua alasan. Pertama untuk memastikan server aman atau yang kedua untuk mengeksploitasi server orang lain. Port yang tidak perlu dibuka berarti port tersebut sudah terbuka dan memiliki kerentanan dan disertai dengan kurangnya keamanan.

Oleh karena itu, sangat masuk akal untuk memindai porta jaringan Anda sendiri untuk menemukan potensi celah keamanan. Untuk melakukannya, kita dapat menggunakan perangkat lunak yang populer dan powerfull seperti Nmap. Namun dalam tutorial ini, kita akan membuat kode untuk memindai port dengan Python. Keuntungan yang kita dapat adalah kita dapat menyesuaikannya sesuai keinginan dan kita bisa belajar sesuatu tentang pemrograman. Kita memilih Python sebagai bahasa karena sederhana, modern, dan sangat powerfull.

Sebelum kita mulai, Anda perlu tahu bahwa pemindaian port jaringan orang lain tanpa izin mereka adalah kejahatan. Pindai hanya jaringan Anda sendiri atau jaringan yang diizinkan. Atau, Anda dapat menggunakan scanme.nmap.org untuk bereksperimen. Saya tidak bertanggung jawab atas penyalahgunaan informasi.

## Dasar-Dasar
Mari kita lihat dulu fungsionalitas dasar pemindai port. Pemindai port mencoba menyambung ke Alamat IP pada port tertentu. Biasanya, ketika kita menjelajahi web, kita terhubung ke server melalui port 80 (HTTP) atau port 443 (HTTPS). Tetapi ada juga banyak port penting lainnya seperti 21 (FTP), 22 (SSH), 25 (SMTP) dan banyak lagi. Faktanya, ada lebih dari 130.000 port yang 1.023 distandarisasi dan 48.128 dicadangkan. Jadi, saat kita membuat pemindai port, lebih baik kita membuatnya seefesien mungkin dan fokus pada port-port penting.

Sekarang, pertama-tama kita akan melihat cara paling sederhana untuk memindai port dengan Python.

```
def portscan(port):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((target, port))
        return True
    except:
        return False
```

Dalam contoh ini, kita membuat soket biasa yang mencoba menyambung ke target menggunakan port tertentu. Jika berhasil, kita mengembalikan nilai True. Jika ada pengecualian atau kesalahan, kita mengembalikan False. Kemudian kita mencetak hasilnya untuk masing-masing port.

Ya, tentu saja, kita juga dapat mengotomatiskannya dengan membuat loop-for yang memindai semua port standar.

```
for port in range(1, 1024):
    result = portscan(port)
    if(result):
        print("Port {} is open!".format(port))
    else:
        print("Port {} is closed!".format(port))
```


Sebenarnya, ini aplikasi pemindai port sudah jadi. Tapi masih ada masalah. Saat Anda menjalankannya, Anda akan melihat bahwa ini sangat lambat, karena memindai port satu demi satu. Hal itu bisa sempurnakan dengan Multithreading. Jadi, mari kita masuk ke kodenya.

## Siapkan Port
Kita perlu mengimport beberapa paket untuk mempermudah pekerjaan, untuk itu mari kita lakukan.

```
from queue import Queue
import socket
import threading
```

Socket akan digunakan untuk mengkoneksikan ke host di port tertentu.
Threading akan memungkinkan kita menjalankan beberapa fungsi pemindaian secara bersamaan.
Queue adalah struktur data yang akan membantu kita mengelola akses beberapa thread pada satu resource, yang dalam kasus ini adalah nomor port. Karena thread kita berjalan secara bersamaan saat memindai port, kita menggunakan queue untuk memastikan bahwa setiap port hanya dipindai satu kali.
Kemudian, kita juga akan membuat tiga variabel global yang nantinya akan kita gunakan di berbagai fungsi:

```
target = "103.131.51.4"
queue = Queue()
open_ports = []
```

Target memiliki nilai yang berupa IP-Address atau domain dari host yang coba kita pindai.
queque untuk sekarang kita kosongkan, nanti kita akan mengisinya dengan port yang ingin kita pindai.
Dan yang tak kalah pentingnya kita memiliki daftar kosong, yang akan menyimpan nomor port terbuka.
Mari kita mulai dengan mengimplementasikan fungsi portscan, seperti contoh di atas.

```
def portscan(port):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((target, port))
        return True
    except:
        return False
```

Di sini Anda dapat melihat blok try-except, di mana kita mencoba untuk terhubung ke target pada port tertentu. Jika berhasil akan mengembalikan True, yang berarti port tersebut terbuka. Jika tidak, code di atas akan mengembalikan False, yang berarti ada kesalahan dan kita asumsikan bahwa port ditutup.

Sekarang, sebelum kita masuk ke threading, kita perlu menentukan port yang ingin kita pindai. Untuk itu, kita akan mendefinisikan fungsi lain yang disebut get_ports .

```
def get_ports(mode):
    if mode == 1:
        for port in range(1, 1024):
            queue.put(port)
    elif mode == 2:
        for port in range(1, 49152):
            queue.put(port)
    elif mode == 3:
        ports = [20, 21, 22, 23, 25, 53, 80, 110, 443]
        for port in ports:
            queue.put(port)
    elif mode == 4:
        ports = input("Enter your ports (spreate by blank):")
        ports = ports.split()
        ports = list(map(int, ports))
        for port in ports:
            queue.put(port)
```

Dalam fungsi ini kita menetapkan empat mode. Mode pertama memindai 1023 port standar. Mode kedua kita menambahkan 48.128 port yang dicadangkan. Dan di mode ketiga kita fokuskan pada beberapa port terpenting. Terakhir, mode keempat memberi kita kemungkinan untuk memilih port kita secara manual. Kemudian kita menambahkan semua port tersebut ke queue.

Mohon diperhatikan, ketika kita memasukan port di mode empat, nilai atau port yang kita inputkan berupa string. Oleh karena itu, kita perlu memetakan fungsi typecasting dari tipe data integer ke setiap elemen list untuk menggunakannya.

## Multithreading
Hal berikutnya yang perlu kita lakukan adalah mendefinisikan fungsi pemindai. Fungsi yang akan bertanggung jawab untuk mendapatkan nomor port dari queue, memindai dan mencetak hasilnya.

```
def pemindai():
    while not queue.empty():
        port = queue.get()
        if portscan(port):
            print("Port {} is open!".format(port))
            open_ports.append(port)
        else:
            print("Port {} is closed!".format(port))
```

Kode di atas cukup sederhana. Selama queue tidak kosong, kita mendapatkan elemen berikutnya dan memindainya. Jika port terbuka, kita mencetaknya begitupun dengan port yang ditutup. Tapi ketika kita mendapatkan port yang terbuka kita akan mendambahkanya ke daftar open_ports.

> Catatan: Kita sangat menyarankan untuk tidak mencetak informasi saat port ditutup, karena informasi ini tidak berguna dan membuat keluaran kita membingungkan.

Okey, sekarang kita bisa mengimplementasikan fungsionalitasnya, kita akan menulis fungsi utama yang membuat, memulai, dan mengelola thread.

```
def run_scanner(threads, mode):
    get_ports(mode)
    thread_list = []

    for t in range(threads):
        thread = threading.Thread(target=pemindai)
        thread_list.append(thread)

    for thread in thread_list:
        thread.start()

    for thread in thread_list:
        thread.join()

    print("Open ports are:", open_ports)
```

Dalam fungsi ini, kita memiliki dua parameter. Yang pertama untuk jumlah thread yang ingin kita mulai dan yang kedua adalah mode. Kita akan memuat port tergantung pada mode yang kita pilih dan kita juga membuat daftar kosong baru untuk menyimpan thread. Kemudian, kita menentukan jumlah thread yang diinginkan, menetapkan fungsi pemindai dan menambahkannya ke list. Setelah itu, kita dapat memulainya dan melihat apakah kode kita berfungsi.

```
run_scanner(100, 1)
```

Dengan menjalankan kode di atas, kode tersebut akan memindai semua port standar. Untuk itu, kita menggunakan seratus thread. yang berarti kita memindai sekitar seratus port per detik. Anda dapat meningkatkan jumlah itu jika Anda mau. Maksimal kecepatanyang bisa saya lakukan dengan komputer saya adalah sekitar 800 pemindaian port per detik.