package main import ( "bufio" "context" "flag" "fmt" "log" "os" "sync" "time" "github.com/libp2p/go-libp2p" dht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/host" "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" ) const protocolID = "/sallik/1.0.0" func main() { rendezvousString := flag.String("r", "gizli-tunel-sifresi", "Buluşma noktası için gizli kelime") flag.Parse() ctx := context.Background() // 1. Libp2p Host'u oluştur (NAT Traversal ve Relay özellikleri açık) h, err := libp2p.New( libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0", "/ip4/0.0.0.0/udp/0/quic-v1"), // TCP ve QUIC dinle libp2p.EnableHolePunching(), // NAT arkasından geçmeyi dene libp2p.EnableNATService(), libp2p.EnableRelay(), // Relay üzerinden geçmeye izin ver ) 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)... Bu biraz sürebilir.") // 2. DHT (Distributed Hash Table) Başlat kademliaDHT, err := dht.New(ctx, h) if err != nil { log.Fatal(err) } // 3. Bootstrap (Başlangıç) Düğümlerine Bağlan if err = kademliaDHT.Bootstrap(ctx); err != nil { log.Fatal(err) } // Halka açık varsayılan IPFS düğümlerine bağlanarak ağa dahil ol 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 { // Bazılarına bağlanamamak normaldir } }() } wg.Wait() fmt.Println("[+] Küresel ağa bağlandık! Şimdi arkadaşın aranıyor...") // 4. Stream Handler (Gelen mesajları karşıla) h.SetStreamHandler(protocolID, handleStream) // 5. Discovery (Keşif) Mekanizması routingDiscovery := routing.NewRoutingDiscovery(kademliaDHT) dutil.Advertise(ctx, routingDiscovery, *rendezvousString) fmt.Printf("[*] '%s' frekansında yayın yapılıyor.\n", *rendezvousString) // 6. 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 // Kendimize bağlanmayalım } fmt.Printf("[?] Bulunan Peer: %s. Bağlanılıyor...\n", peer.ID) // Bağlantı dene if err := h.Connect(ctx, peer); err != nil { // Bağlantı başarısız olabilir (henüz delik açılmamış olabilir), tekrar deneriz continue } fmt.Printf("[+] BAĞLANTI BAŞARILI! Tünel Kuruldu: %s\n", peer.ID) // Stream aç 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 // Bir kişi bulduk ve bağlandık, aramayı durdur (isteğe bağlı) } time.Sleep(time.Second * 2) // Kimse yoksa 2 saniye sonra tekrar ara } }() select {} // Programı açık tut } 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() } }