Python 提供了多種方式與 Tor 網路互動,實作匿名瀏覽和存取隱藏服務。Stem 模組允許直接與 Tor 控制器通訊,執行更換身份、查詢電路狀態、取得伺服器描述符等操作。torpy 模組則提供純 Python 的 Tor 協定實作,無需依賴外部 Tor 客戶端。此外,torrequest 模組簡化了透過 Tor 傳送 HTTP 請求的流程,並提供更靈活的控制選項。透過結合 requests 模組,可以輕鬆實作定時更換 IP 地址,提升匿名性。除了連線 Tor 網路,文章也介紹瞭如何利用 Stem 取得隱藏服務的描述符和介紹點,以及使用 TorBot 等工具搜尋暗網資源,提供更全面的 Tor 網路探索方案。
使用Python連線Tor網路與發現隱藏服務
在前面的程式碼中,我們看到了Tor如何使用9050埠作為預設的SOCKS埠,並透過socks5h://127.0.0.1:9050字串進行連線。接著,它預設會印出你的公眾IP地址。透過get_tor_session()方法,我們建立了一個透過SOCKS代理的Tor連線。這樣做會改變我們的IP地址,並印出與預設IP地址不同的IP。
一旦我們獲得了與Tor網路的連線會話,我們就可以查詢隱藏的網路服務;例如,我們可以向位於http://3g2upl4pq6kufc4m.onion的Duckduckgo網站發出請求,並獲得回應標頭。
另一種透過Tor網路發出請求的方式是使用torrequest介面(https://github.com/erdiaker/torrequest)。你可以使用pip install torrequest命令進行安裝。
主要的類別可以在以下GitHub儲存函式庫中找到:https://github.com/erdiaker/torrequest/blob/master/torrequest.py。
TorRequest物件還暴露了底層的stem控制器和請求會話物件,以增加靈活性。
你可以在tor_request.py檔案中找到以下程式碼:
from torrequest import TorRequest
with TorRequest(proxy_port=9050, ctrl_port=9051, password=None) as tr:
response = tr.get('http://ipecho.net/plain')
print(response.text)
print(type(tr.ctrl))
tr.ctrl.signal('CLEARDNSCACHE')
tr.reset_identity()
response = tr.get('http://httpbin.org/ip')
print(response.text)
內容解密:
在上述程式碼中,TorRequest類別作為與Stem控制器的介面。在這種情況下,我們使用來自torRequest物件的get()方法進行請求。要獲得新的身份,我們可以使用來自該物件的reset_identity()方法。
使用torpy模組連線Tor網路
另一種方法是使用torpy模組,它是一個純Python的Tor協定實作。在這種情況下,既不需要原生的Tor客戶端,也不需要Stem依賴。你可以在以下GitHub儲存函式庫中找到該模組的原始碼:https://github.com/torpyorg/torpy。
使用以下命令在本地儲存函式庫中安裝該模組:
$ pip3 install torpy
你可以在test-torpy.py檔案中找到以下程式碼:
from torpy.http.requests import TorRequests
with TorRequests() as tor_requests:
print("building circuit...")
with tor_requests.get_session() as session:
print(session.get("http://httpbin.org/ip").json())
print("renewing circuit...")
with tor_requests.get_session() as session:
print(session.get("http://httpbin.org/ip").json())
response = session.get('http://3g2upl4pq6kufc4m.onion')
for key, value in response.headers.items():
print(key, value)
內容解密:
在上述程式碼中,我們使用來自torpy.http.requests套件的TorRequests類別來建立電路。我們可以看到,每次使用來自該類別的get_session()方法時,它都會在內部更新電路並獲得新的IP地址。
使用Stem模組從Tor網路中提取資訊
Stem(https://stem.torproject.org)是一個用Python編寫的模組,它對Tor客戶端和目錄權威執行各種操作。你可以使用以下命令安裝此模組:
$ pip3 install stem
透過Stem收集的資訊對於收集有關Tor網路中可用中繼器的資訊非常有用。它不僅允許你控制例項,還允許你取得授權的目錄描述符和其他節點在Tor網路上。
使用stem模組,我們基本上可以與Tor控制器進行通訊,以程式設計方式向Tor控制埠傳送和接收命令。例如,我們可以使用該模組的信令方法來獲得新的身份並建立新的電路。
你可以檢視Tor的協定規範,網址是https://gitweb.torproject.org/torspec.git/tree/control-spec.txt。在此規範中,我們可以看到可以用來存取Tor連線特定資訊的鍵,例如其版本、組態檔案、電路狀態、組態選項、事件等。
使用Python建立透過Tor的請求
另一種使用Python建立透過Tor的請求的方式是建立以下函式,所有這些函式都可以在anonymize.py指令碼中找到:
enable_proxy(host="127.0.0.1", port=9050):啟動代理並接收主機和埠作為引數。預設情況下,這些是localhost和9050。注意9050是Tor的預設埠。disable_proxy():移除通訊端“補丁”。
你可以在anonymize.py檔案中找到以下程式碼:
import socks
import socket
temp_socket = socket.socket
temp_create_connection = socket.create_connection
def disable_proxy():
socket.socket = temp_socket
socket.create_connection = temp_create_connection
def enable_proxy(host="127.0.0.1", port=9050):
def create_connection(address, timeout=None, source_address=None):
sock = socks.socksocket()
sock.connect(address)
return sock
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, host, port, True)
socket.socket = socks.socksocket
socket.create_connection = create_connection
內容解密:
在上述程式碼中,我們定義了兩個函式:enable_proxy()和disable_proxy()。enable_proxy()函式啟動SOCKS代理,而disable_proxy()函式則停用它。我們可以使用這些函式來測試透過Tor發出的請求是否成功匿名化。
使用Python中的模組和套件連線Tor網路
在前面的章節中,我們已經瞭解了Tor網路的基本概念和架構。在本章節中,我們將介紹如何使用Python中的模組和套件來連線Tor網路並取得相關資訊。
Stem套件介紹
Stem是一個Python套件,提供了對Tor網路的程式化存取。透過Stem,我們可以取得Tor網路中的各種描述符(descriptor),例如伺服器描述符、額外資訊描述符、微描述符等。
取得Tor網路中的描述符
Tor網路中的每個重傳器(repeater)都會向客戶端公開相關資訊,這些資訊被稱為描述符。描述符包含了Tor網路的狀態資訊,例如重傳器的狀態、頻寬等。
以下是幾種常見的描述符型別:
- 伺服器描述符:包含了重傳器的完整資訊(目前客戶端已不再下載此檔案,改用微描述符)。
- 額外資訊描述符:包含了Tor節點作為重傳器的使用統計資訊。
- 微描述符:僅包含了Tor客戶端與重傳器通訊所需的必要資訊。
- 共識(網路狀態):由授權的網路實體釋出的檔案,包含了多個重傳器的資訊輸入(路由器狀態輸入)。
- 路由器狀態條目:包含了網路上某個重傳器的資訊。
使用Stem取得描述符
以下是一個使用Stem套件取得共識描述符的範例程式碼:
from stem.descriptor.remote import DescriptorDownloader
downloader = DescriptorDownloader()
descriptors = downloader.get_consensus().run()
for descriptor in descriptors:
print('Nickname:', descriptor.nickname)
print('Fingerprint:', descriptor.fingerprint)
print('Address:', descriptor.address)
print('Bandwidth:', descriptor.bandwidth)
內容解密:
- 匯入
DescriptorDownloader類別:用於下載Tor網路中的描述符。 - 建立
DescriptorDownloader物件:用於下載共識描述符。 - 呼叫
get_consensus().run()方法:下載共識描述符並執行。 - 遍歷描述符列表:印出每個描述符的暱稱、指紋、位址和頻寬。
取得電路狀態
以下是一個使用Stem套件取得電路狀態的範例程式碼:
from stem.control import Controller
controller = Controller.from_port(port=9051)
controller.authenticate()
print(controller.get_info('circuit-status'))
內容解密:
- 匯入
Controller類別:用於控制Tor例項。 - 建立
Controller物件:連線到控制埠9051。 - 呼叫
authenticate()方法:驗證控制連線。 - 呼叫
get_info('circuit-status')方法:取得電路狀態。
列出所有電路
以下是一個使用Stem套件列出所有電路的範例程式碼:
from stem import CircStatus
from stem.control import Controller
with Controller.from_port(port=9051) as controller:
controller.authenticate()
for circ in sorted(controller.get_circuits()):
if circ.status != CircStatus.BUILT:
continue
print("Circuit %s (%s)" % (circ.id, circ.purpose))
for i, entry in enumerate(circ.path):
div = '+' if (i == len(circ.path) - 1) else '|'
fingerprint, nickname = entry
desc = controller.get_network_status(fingerprint, None)
address = desc.address if desc else 'unknown'
print(" %s- %s (%s, %s)" % (div, fingerprint, nickname, address))
內容解密:
- 匯入
CircStatus和Controller類別:用於控制Tor例項和取得電路狀態。 - 建立
Controller物件:連線到控制埠9051。 - 呼叫
authenticate()方法:驗證控制連線。 - 呼叫
get_circuits()方法:取得所有電路。 - 遍歷電路列表:印出每個電路的ID、目的和路徑。
取得伺服器描述符
以下是一個使用Stem套件取得伺服器描述符的範例程式碼:
from stem.descriptor.remote import DescriptorDownloader
downloader = DescriptorDownloader()
descriptors = downloader.get_server_descriptors().run()
for descriptor in descriptors:
print('Descriptor', str(descriptor))
print('Certificate', descriptor.certificate)
內容解密:
- 匯入
DescriptorDownloader類別:用於下載Tor網路中的描述符。 - 建立
DescriptorDownloader物件:用於下載伺服器描述符。 - 呼叫
get_server_descriptors().run()方法:下載伺服器描述符並執行。 - 遍歷描述符列表:印出每個描述符的字串表示和憑證。
使用Python連線Tor網路的模組與套件
在Python中,我們可以使用多個模組和套件來連線Tor網路並提取相關資訊。這些工具為開發者提供了豐富的功能,以便與Tor網路互動並取得隱藏服務的資訊。
使用Stem模組與Tor控制器互動
Stem是一個用於與Tor控制器互動的Python函式庫。它提供了豐富的功能,包括取得伺服器描述符、隱藏服務描述符以及更換身份等。
取得伺服器描述符
伺服器描述符包含了有關Tor節點的重要資訊,如其IP地址、埠和金鑰等。以下程式碼展示瞭如何使用Stem取得伺服器描述符:
from stem.descriptor import DescriptorDownloader
downloader = DescriptorDownloader()
descriptors = downloader.get_server_descriptors()
for descriptor in descriptors:
print('伺服器指紋:', descriptor.fingerprint)
print('Onion金鑰:', descriptor.onion_key)
print('簽名金鑰:', descriptor.signing_key)
print('簽名:', descriptor.signature)
內容解密:
DescriptorDownloader類別用於下載Tor伺服器描述符。get_server_descriptors()方法傳回一個包含多個伺服器描述符的列表。- 迴圈遍歷每個描述符並列印其指紋、Onion金鑰、簽名金鑰和簽名。
取得隱藏服務描述符
隱藏服務描述符提供了有關.onion地址的詳細資訊,包括其介紹點。以下程式碼展示瞭如何取得DuckDuckGo的隱藏服務描述符:
from stem.control import Controller
with Controller.from_port(port=9051) as controller:
controller.authenticate()
desc = controller.get_hidden_service_descriptor('3g2upl4pq6kufc4m')
print("DuckDuckGo的介紹點是...\n")
for introduction_point in desc.introduction_points():
print(' %s:%s => %s' % (introduction_point.address, introduction_point.port, introduction_point.identifier))
內容解密:
Controller類別用於與Tor控制器建立連線。get_hidden_service_descriptor()方法用於取得指定.onion地址的隱藏服務描述符。- 遍歷介紹點並列印其地址、埠和識別符。
更換Tor身份
Stem還允許我們以程式設計方式更換Tor身份,取得新的IP地址。以下程式碼展示瞭如何使用Signal.NEWNYM訊號更換身份:
from stem import Signal
from stem.control import Controller
with Controller.from_port(port=9051) as controller:
controller.authenticate()
print("成功連線!")
controller.signal(Signal.NEWNYM)
print("新的Tor連線已處理")
內容解密:
Signal.NEWNYM訊號用於請求新的Tor電路,從而獲得新的出口節點和IP地址。controller.signal(Signal.NEWNYM)方法傳送訊號給Tor控制器以更換身份。
結合Requests模組使用Stem
我們可以結合Requests模組和Stem來定期更換IP地址並透過Tor網路傳送請求。以下程式碼展示瞭如何每5秒更換一次IP地址:
import time
from stem import Signal
from stem.control import Controller
import requests
def get_tor_session():
session = requests.session()
session.proxies = {'http': 'socks5h://127.0.0.1:9050', 'https': 'socks5h://127.0.0.1:9050'}
return session
def main():
while True:
time.sleep(5)
print("正在輪換IP...")
with Controller.from_port(port=9051) as controller:
controller.authenticate()
controller.signal(Signal.NEWNYM)
session = get_tor_session()
print(session.get("http://httpbin.org/ip").text)
if __name__ == '__main__':
main()
內容解密:
get_tor_session()函式建立一個透過Tor代理的Requests會話。- 在
main()函式中,每5秒更換一次Tor身份並傳送請求以取得可見的IP地址。
使用TorBot進行隱藏服務搜尋
TorBot是一個用於暗網的OSINT工具,可以用來收集.onion網域名稱的資訊。以下是如何使用TorBot的簡要步驟:
- 啟動Tor服務:
sudo service tor start - 確保
torrc組態正確,SOCKS_PORT設為9050。 - 安裝必要的Python依賴:
pip3 install -r requirements.txt - 執行TorBot:
python3 torBot.py -i -u http://cnkj6nippubgycuj.onion/search?query=bitcoin&action=search
TorBot允許使用者提取與特定主題相關的連結,並將結果儲存為JSON等格式。