192 lines
4.6 KiB
Go
192 lines
4.6 KiB
Go
package main
|
||
|
||
import (
|
||
"bufio"
|
||
"context"
|
||
"flag"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
|
||
"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-chat/1.0.0"
|
||
|
||
// IPFS'in resmi Relay sunucuları (Halka açık ve güvenilir)
|
||
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 gizli kelime")
|
||
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(),
|
||
|
||
// MANUEL RELAY AYARI (Hata çözen kısım)
|
||
// Hazır fonksiyon yerine yukarıdaki listeyi kullanıyoruz.
|
||
libp2p.EnableAutoRelay(autorelay.WithStaticRelays(staticRelays)),
|
||
|
||
libp2p.ForceReachabilityPrivate(),
|
||
)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
fmt.Printf("[*] Düğüm Başladı ID: %s\n", h.ID())
|
||
fmt.Println("[*] Küresel ağa bağlanılıyor (Bootstrapping)...")
|
||
|
||
// 3. DHT Başlat (ModeClient)
|
||
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 Düğümlerine Bağlan
|
||
var wg sync.WaitGroup
|
||
for _, peerAddr := range dht.DefaultBootstrapPeers {
|
||
peerinfo, _ := peer.AddrInfoFromP2pAddr(peerAddr)
|
||
wg.Add(1)
|
||
go func() {
|
||
defer wg.Done()
|
||
if err := h.Connect(ctx, *peerinfo); err != nil {
|
||
}
|
||
}()
|
||
}
|
||
wg.Wait()
|
||
fmt.Println("[+] IPFS Ağına Bağlanıldı.")
|
||
|
||
// 5. RELAY ADRESİ BEKLEME DÖNGÜSÜ
|
||
fmt.Print("[*] Bir Relay sunucusundan yer ayrılması 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! Artık erişilebilirsin.")
|
||
break
|
||
}
|
||
fmt.Print(".")
|
||
time.Sleep(time.Second * 1)
|
||
}
|
||
|
||
// 6. Stream Handler
|
||
h.SetStreamHandler(protocolID, handleStream)
|
||
|
||
// 7. Discovery (Keşif)
|
||
routingDiscovery := routing.NewRoutingDiscovery(kademliaDHT)
|
||
dutil.Advertise(ctx, routingDiscovery, *rendezvousString)
|
||
fmt.Printf("[*] '%s' frekansında yayın yapılıyor.\n", *rendezvousString)
|
||
|
||
// 8. Arkadaşı Ara ve Bağlan
|
||
go func() {
|
||
for {
|
||
peerChan, err := routingDiscovery.FindPeers(ctx, *rendezvousString)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
|
||
for peer := range peerChan {
|
||
if peer.ID == h.ID() {
|
||
continue
|
||
}
|
||
|
||
fmt.Printf("[?] Bulunan Peer: %s. Bağlanılıyor...\n", peer.ID)
|
||
|
||
ctxConnect, cancel := context.WithTimeout(ctx, time.Second*30)
|
||
err := h.Connect(ctxConnect, peer)
|
||
cancel()
|
||
|
||
if err != nil {
|
||
fmt.Printf("\x1b[31m[!] HATA: %s\x1b[0m\n", err)
|
||
continue
|
||
}
|
||
|
||
fmt.Printf("[+] BAĞLANTI BAŞARILI! Tünel Kuruldu: %s\n", peer.ID)
|
||
|
||
stream, err := h.NewStream(ctx, peer.ID, protocolID)
|
||
if err != nil {
|
||
fmt.Println("Stream hatası:", err)
|
||
continue
|
||
}
|
||
|
||
rw := bufio.NewReadWriter(bufio.NewReader(stream), bufio.NewWriter(stream))
|
||
go readData(rw)
|
||
go writeData(rw)
|
||
return
|
||
}
|
||
time.Sleep(time.Second * 3)
|
||
}
|
||
}()
|
||
|
||
select {}
|
||
}
|
||
|
||
func handleStream(s network.Stream) {
|
||
fmt.Println("\n[!] Biri tünelimize giriş yaptı!")
|
||
rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
|
||
go readData(rw)
|
||
go writeData(rw)
|
||
}
|
||
|
||
func readData(rw *bufio.ReadWriter) {
|
||
for {
|
||
str, err := rw.ReadString('\n')
|
||
if err != nil {
|
||
return
|
||
}
|
||
fmt.Printf("\x1b[32m%s\x1b[0m: %s", "Gelen", str)
|
||
}
|
||
}
|
||
|
||
func writeData(rw *bufio.ReadWriter) {
|
||
stdReader := bufio.NewReader(os.Stdin)
|
||
for {
|
||
fmt.Print("> ")
|
||
sendData, _ := stdReader.ReadString('\n')
|
||
rw.WriteString(sendData)
|
||
rw.Flush()
|
||
}
|
||
} |