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() } }