代理伺服器掃描和埠掃描是網路安全領域中重要的技術手段,可用於檢測網路漏洞和評估系統安全性。本文提供的 Python 程式碼範例示範瞭如何掃描特定 IP 範圍內的開放代理伺服器,並利用這些代理進行埠掃描。程式碼利用 Socket 模組建立網路連線,並透過 HTTP CONNECT 命令與代理伺服器互動。此外,文章還解析瞭如何根據 HTTP 狀態碼判斷連線結果,並提供了一些實務應用中的改進建議,例如多執行緒處理、錯誤處理、日誌記錄以及動態 IP 範圍生成等。這些技術的結合可以幫助網路安全人員更有效地發現網路中的潛在風險,並提升系統的安全性。

Proxy Scanner

開放代理對於匿名上網非常有用。根據其組態,我們甚至可以透過發出 CONNECT 命令來串聯多個代理。此外,代理還提供了連線到通常被防火牆阻止的主機和埠的機會。然而,誤組態的代理可能成為進入內部網路的一個漏洞。

在 2002 年,《紐約時報》就曾因為被誤組態的代理洩露內部網路而遭受攻擊。因此,撰寫一個程式來掃描 IP 範圍內開放的代理伺服器是非常有必要的。

我們可以嘗試直接連線到常見的代理埠(如 3128 和 8080)來檢測開放代理伺服器。如果沒有其他指示,它將嘗試存取 Google 以確認該代理是否正常工作。

指令碼範例

以下是一個簡單的 Proxy Scanner 指令碼範例:

import socket

def scan_proxy(ip, port):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        result = sock.connect_ex((ip, port))
        if result == 0:
            print(f"Proxy found at {ip}:{port}")
        sock.close()
    except Exception as e:
        print(f"Error scanning {ip}:{port} - {e}")

def main():
    ip_range = "192.168.1.0/24"
    ports = [3128, 8080]
    for ip in range_ip(ip_range):
        for port in ports:
            scan_proxy(ip, port)

if __name__ == "__main__":
    main()

內容解密:

這段指令碼主要用於掃描特定 IP 範圍內開放的代理伺服器。具體步驟如下:

  1. 匯入所需模組:匯入 Python 的 socket 模組以進行網路連線。
  2. 定義 scan_proxy 函式:這個函式嘗試連線到指定 IP 和埠。
  3. 建立連線:使用 socket 建立連線並設定超時時間為 1秒。
  4. 檢查連線結果:如果連線成功(傳回值為0),則輸出該 IP 和埠號。
  5. 關閉連線:無論成功與否都關閉 socket。
  6. 定義 main 函式:迴圈掃描特定 IP 範圍和埠號。
  7. 執行 main 函式:當作為主程式執行時啟動掃描。

HTTP 代理伺服器掃描與埠掃描技術

HTTP 代理伺服器是網路安全中的一個重要議題,許多攻擊者會利用開放的代理伺服器進行各種非法活動。因此,識別和掃描開放的代理伺服器成為了資安專家的重要工作之一。此外,利用這些代理伺服器進行埠掃描也是一種常見的技術手段。以下將詳細介紹如何使用 Python 來實作這兩項技術。

開放代理伺服器掃描

開放的代理伺服器可能會回應 HTTP 200 狀態碼並顯示自訂錯誤頁面,這使得自動化檢測變得複雜。因此,工具通常會傳回整個 HTML 程式碼,讓使用者自己判斷請求是否成功。

#!/usr/bin/env python3

import sys
import os
import socket
import urllib.request
from random import randint

# 常用的代理伺服器埠
proxy_ports = [3128, 8080, 8181, 8000, 1080, 80]

# 嘗試抓取的 URL
get_host = "www.google.com"
socket.setdefaulttimeout(3)

# 從起始 IP 和結束 IP 取得 IP 清單
def get_ips(start_ip, stop_ip):
    ips = []
    tmp = []

    for i in start_ip.split('.'):
        tmp.append("%.2X" % int(i))

    start_dec = int(''.join(tmp), 16)
    tmp = []

    for i in stop_ip.split('.'):
        tmp.append("%.2X" % int(i))

    stop_dec = int(''.join(tmp), 16)

    while start_dec < stop_dec + 1:
        bytes = []
        bytes.append(str(int(start_dec / 16777216)))
        rem = start_dec % 16777216
        bytes.append(str(int(rem / 65536)))
        rem = rem % 65536
        bytes.append(str(int(rem / 256)))
        rem = rem % 256
        bytes.append(str(rem))
        ips.append(".".join(bytes))
        start_dec += 1

    return ips

# 嘗試連線到代理並抓取 URL
def proxy_scan(ip):
    for port in proxy_ports:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((ip, port))
            print(ip + ":" + str(port) + " OPEN")

            req = "GET " + get_host + " HTTP/1.0\r\n"
            print(req)
            s.send(req.encode())
            s.send("\r\n".encode())

            while True:
                data = s.recv(1024)
                if not data:
                    break
                print(data.decode())

            s.close()
        except socket.error:
            print(ip + ":" + str(port) + " Connection refused")

# 處理引數
if len(sys.argv) < 2:
    print(sys.argv[0] + ": <start_ip - stop_ip>")
    sys.exit(1)
else:
    if len(sys.argv) == 3:
        get_host = sys.argv[2]

if sys.argv[1].find('-') > 0:
    start_ip, stop_ip = sys.argv[1].split("-")
    ips = get_ips(start_ip, stop_ip)

    while len(ips) > 0:
        i = randint(0, len(ips) - 1)
        lookup_ip = str(ips[i])
        del ips[i]
        proxy_scan(lookup_ip)
else:
    proxy_scan(sys.argv[1])

內容解密:

這段程式碼的主要功能是掃描一個 IP 範圍內的開放代理伺服器。以下是詳細解說:

  1. 匯入模組:程式碼首先匯入了 sysossocketurllib.requestrandom 模組,這些模組提供了基本的系統操作、網路操作和隨機數生成功能。

  2. 定義常用埠proxy_ports 傳達了一些常見的代理伺服器埠,這些埠通常會被用來進行代理連線。

  3. 設定目標 URLget_host 暫存目標 URL,這裡設定為 Google 的首頁。socket 的超時時間也被設定為3秒。

  4. 生成 IP 清單get_ips 函式根據起始和結束 IP 地址生成一個 IP 清單。它將 IP 地址轉換為十六進位制格式,然後逐步增大十六進位制值以生成連續的 IP 地址。

  5. 檢查每個 IP 的開放代理proxy_scan 函式嘗試連線每個 IP 的指定埠。如果連線成功,則傳送一個 HTTP GET 請求並列印回應內容。如果連線失敗,則列印錯誤訊息。

傳統埠掃描技術

在瞭解瞭如何找到開放的代理伺服器後,我們可以利用這些代理伺服器來進行埠掃描。HTTP CONNECT 命令允許我們指定目的地主機和 TCP 埠,即使對方不是 HTTP 網站也能取得埠是否可通訊。

#!/usr/bin/env python3

import sys
from socket import socket, AF_INET, SOCK_STREAM, error as SocketError

if len(sys.argv) < 4:
    print(sys.argv[0] + ": <proxy> <port> <target>")
    sys.exit(1)

# 對每個感興趣的埠進行掃描
for port in (21, 22, 23, 25, 80, 443, 8080, 3128):
    sock = socket(AF_INET, SOCK_STREAM)
    try:
        sock.connect((sys.argv[1], int(sys.argv[2])))
    except SocketError:
        print(sys.argv[1] + ":" + sys.argv[2] + " connection refused")
        break

    print("Trying to connect to %s:%d through %s:%s" %
          (sys.argv[3], port, sys.argv[1], sys.argv[2]))
    connect = "CONNECT " + sys.argv[3] + ":" + str(port) + " HTTP/1.1\r\n\r\n"
    sock.send(connect.encode())

    resp = sock.recv(1024).decode()

    try:
        status = int(resp.split(" ")[1])
        if status == 200:
            print(f"Port {port} is open on {sys.argv[3]}")
        else:
            print(f"Port {port} is closed on {sys.argv[3]}")
    except (IndexError, ValueError):
        print("Failed to parse response")

內容解密:

這段程式碼的主要功能是利用已知的開放代理伺服器來進行埠掃描。以下是詳細解說:

  1. 匯入模組:程式碼首先匯入了 syssocket 模組,這些模組提供了基本的系統操作和網路操作功能。

  2. 檢查引數:程式碼檢查輸入引數,確保使用者提供了足夠的引數(代理、埠和目標)。

  3. 對每個感興趣的埠進行掃描:程式碼遍歷了一些常見的埠(如 FTP、SSH、Telnet、SMTP、HTTP、HTTPS等)。

  4. 建立 TCP 連結:使用 socket.connect() 建立到目標代理伺服器的 TCP 連結。如果連線失敗,則列印錯誤訊息並離開。

  5. 傳送 HTTP CONNECT 命令:向代理伺服器傳送 HTTP CONNECT 命令,指定目標主機和埠。然後接收回應並解析狀態碼。

應用與改進點

這兩段程式碼展示瞭如何利用 Python 掃描開放代理伺服器以及如何利用這些代理來進行埠掃描。在實務應用中,可以考慮以下幾點改進:

  • 多執行緒處理:使用多執行緒來加速掃描過程。
  • 錯誤處理:增加更多錯誤處理機制,以應對網路異常或其他異常情況。
  • 日誌記錄:增加日誌記錄功能,方便後續分析和稽核。
  • 動態 IP 範圍:根據需要動態生成 IP 範圍,而不是硬編碼在程式碼中。
  • 反向鑒識: 改進反向鑒識技術來預防被對方拒絕.

透過這些改進,可以使得掃描工具更加高效且穩定。

使用代理檢測開放的網路埠

在這一段程式碼中,玄貓將介紹如何使用代理檢測目標主機上的開放埠。這是一個常見的網路安全測試技術,可以幫助我們評估系統的安全性。以下是程式碼的詳細解說與邏輯。

執行流程與邏輯

以下是代理檢測開放埠的具體程式碼範例:

status = None

# 當狀態為200時,表示連線成功
if status == 200:
    get = "GET / HTTP/1.0\r\n\r\n"
    sock.send(get.encode())
    resp = sock.recv(1024)
    print("Port " + str(port) + " is open")
    print(resp)

# 當狀態在400到499之間時,表示代理拒絕處理請求
elif status >= 400 and status < 500:
    print("Bad proxy! Scanning denied.")
    break

# 當狀態大於等於500時,表示埠已關閉
elif status >= 500:
    print("Port " + str(port) + " is closed")
else:
    print("Unknown error! Got " + resp)

sock.close()

內容解密:

  1. 變數初始化:首先,我們初始化一個變數 status,用來儲存連線的狀態碼。
  2. 狀態檢查:透過 ifelifelse 陳述式來檢查狀態碼,根據不同的狀態碼執行相應的操作。
  3. 傳送 GET 請求:當狀態碼為200時,表示連線成功,我們傳送一個 GET 請求給目標主機,並接收回應。
  4. 處理回應:根據回應的內容判斷該埠是否開放。
  5. 關閉連線:無論結果如何,最後我們都會關閉通訊端連線。

技術細節與考量

  1. HTTP 版本選擇:在這個範例中,我們使用了 HTTP/1.0 來傳送 GET 請求。這是因為我們希望避免新增額外的 Host 標頭,以確保對方能夠正確解析請求。
  2. 狀態碼處理:根據不同的 HTTP 狀態碼來判斷連線的結果。例如,400-499 的狀態碼表示代理拒絕處理請求,而 502、503 或 504 的狀態碼則表示遠端主機未回應或被防火牆過濾。
  3. 錯誤處理:當遇到未知錯誤時,我們輸出錯誤資訊並結束連線。

這段程式碼展示瞭如何使用代理來檢測目標主機上的開放埠。透過分析 HTTP 回應和狀態碼,我們可以有效地評估目標系統的安全性。這種方法在網路安全測試中非常常見,特別是在測試防火牆和其他網路安全裝置時。