Files
p2pNetwork/main.go
Atakan Özgün 22ef96fc67 vpn
2025-12-04 04:16:40 +03:00

222 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"context"
"flag"
"fmt"
"io"
"log"
"net"
"strings"
"sync"
"time"
"github.com/armon/go-socks5"
"github.com/libp2p/go-libp2p"
dht "github.com/libp2p/go-libp2p-kad-dht"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/discovery/routing"
dutil "github.com/libp2p/go-libp2p/p2p/discovery/util"
"github.com/libp2p/go-libp2p/p2p/host/autorelay"
"github.com/multiformats/go-multiaddr"
)
const protocolID = "/onion-proxy/1.0.0"
// IPFS Statik Relay Listesi
var relayNodes = []string{
"/ip4/147.75.83.83/tcp/4001/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
"/ip4/147.75.76.67/tcp/4001/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
"/ip4/147.75.109.213/tcp/4001/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
}
func main() {
rendezvousString := flag.String("r", "gizli-tunel-sifresi", "Buluşma noktası için şifre")
proxyPort := flag.String("proxy", "", "Client modu: Yerel SOCKS5 portu (Örn: 1080)")
flag.Parse()
ctx := context.Background()
// 1. Statik Relay Listesini Hazırla
var staticRelays []peer.AddrInfo
for _, s := range relayNodes {
ma, err := multiaddr.NewMultiaddr(s)
if err != nil {
continue
}
ai, err := peer.AddrInfoFromP2pAddr(ma)
if err != nil {
continue
}
staticRelays = append(staticRelays, *ai)
}
// 2. Libp2p Host'u oluştur
h, err := libp2p.New(
libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0", "/ip4/0.0.0.0/udp/0/quic-v1"),
libp2p.EnableHolePunching(),
libp2p.EnableNATService(),
libp2p.EnableRelay(),
libp2p.EnableAutoRelay(autorelay.WithStaticRelays(staticRelays)),
libp2p.ForceReachabilityPrivate(),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("[*] Düğüm ID: %s\n", h.ID())
fmt.Println("[*] Küresel ağa bağlanılıyor (Bootstrapping)...")
// 3. DHT Başlat
kademliaDHT, err := dht.New(ctx, h, dht.Mode(dht.ModeClient))
if err != nil {
log.Fatal(err)
}
if err = kademliaDHT.Bootstrap(ctx); err != nil {
log.Fatal(err)
}
// 4. Bootstrap
var wg sync.WaitGroup
for _, peerAddr := range dht.DefaultBootstrapPeers {
peerinfo, _ := peer.AddrInfoFromP2pAddr(peerAddr)
wg.Add(1)
go func() {
defer wg.Done()
h.Connect(ctx, *peerinfo)
}()
}
wg.Wait()
fmt.Println("[+] IPFS Ağına Bağlanıldı.")
// 5. Relay Bekleme
fmt.Print("[*] Relay bekleniyor...")
for {
hasRelay := false
for _, addr := range h.Addrs() {
if strings.Contains(addr.String(), "p2p-circuit") {
hasRelay = true
break
}
}
if hasRelay {
fmt.Println("\n[+] Relay Tüneli Hazır!")
break
}
fmt.Print(".")
time.Sleep(time.Second * 1)
}
// ==========================================
// ROLLERE GÖRE AYRIŞMA (SERVER vs CLIENT)
// ==========================================
// EXIT NODE (SERVER) MANTIĞI:
// Gelen tüm stream isteklerini SOCKS5 sunucusuna yönlendir.
socksConf := &socks5.Config{}
socksServer, err := socks5.New(socksConf)
if err != nil {
panic(err)
}
h.SetStreamHandler(protocolID, func(s network.Stream) {
fmt.Println("\n[->] Tünelden yeni bir internet isteği geldi!")
// Gelen libp2p akışını doğrudan SOCKS5 sunucusuna teslim et
// SOCKS5 sunucusu internete bağlanıp cevabı stream'e geri yazacak.
socksServer.ServeConn(s)
})
// Discovery Başlat
routingDiscovery := routing.NewRoutingDiscovery(kademliaDHT)
dutil.Advertise(ctx, routingDiscovery, *rendezvousString)
fmt.Printf("[*] '%s' kanalında dinleniyor.\n", *rendezvousString)
// CLIENT (KULLANICI) MANTIĞI:
// Eğer -proxy 1080 bayrağı verildiyse, yerel portu dinle ve trafiği tünele at.
if *proxyPort != "" {
go startLocalProxy(ctx, h, routingDiscovery, *rendezvousString, *proxyPort)
}
select {} // Sonsuz bekleme
}
// startLocalProxy: Tarayıcıdan gelen trafiği yakalar ve tünele atar
func startLocalProxy(ctx context.Context, h network.Network, discovery *routing.RoutingDiscovery, rendezvous, port string) {
fmt.Println("------------------------------------------------")
fmt.Printf("[CLIENT MODU] Yerel Proxy Başlatıldı: 127.0.0.1:%s\n", port)
fmt.Println("Tarayıcının SOCKS5 ayarını buraya yönlendir.")
fmt.Println(ıkış Düğümü (Exit Node) aranıyor...")
fmt.Println("------------------------------------------------")
var targetPeer peer.AddrInfo
found := false
// 1. Çıkış Düğümü Bul (Sadece bir tane bulmak yeterli)
for !found {
peerChan, err := discovery.FindPeers(ctx, rendezvous)
if err != nil {
panic(err)
}
for p := range peerChan {
if p.ID == h.LocalPeer() {
continue
}
// Bulunan kişiye bağlanmayı dene
if err := h.DialPeer(ctx, p.ID); err == nil {
fmt.Printf("[+] Çıkış Düğümü Bulundu ve Bağlandı: %s\n", p.ID)
targetPeer = p
found = true
break
}
}
if !found {
time.Sleep(time.Second * 1)
}
}
// 2. Yerel TCP Portunu Dinle (Örn: 1080)
listener, err := net.Listen("tcp", ":"+port)
if err != nil {
log.Fatal(err)
}
for {
// Tarayıcıdan gelen isteği kabul et
conn, err := listener.Accept()
if err != nil {
log.Println("Accept hatası:", err)
continue
}
// Her yeni istek için tünel üzerinden yeni bir stream aç
go func(browserConn net.Conn) {
defer browserConn.Close()
// Çıkış düğümüne stream aç
stream, err := h.NewStream(ctx, targetPeer.ID, protocolID)
if err != nil {
log.Println("Tünel açma hatası (Arkadaşın düştü mü?):", err)
return
}
defer stream.Close()
// Veriyi İki Yönlü Kopyala (Pipe)
// Browser -> Tünel -> Arkadaş -> İnternet
// İnternet -> Arkadaş -> Tünel -> Browser
var wg sync.WaitGroup
wg.Add(2)
go func() {
io.Copy(stream, browserConn)
wg.Done()
}()
go func() {
io.Copy(browserConn, stream)
wg.Done()
}()
wg.Wait()
}(conn)
}
}