ztip

zero-trust i2p coordinator
git clone git@git.kloet.net/ztip.git
Download | Log | Files | Refs | README

ztip.go (2174B)


      1 package main
      2 
      3 import (
      4 	"io"
      5 	"log"
      6 	"net"
      7 	"time"
      8 
      9 	sam3 "github.com/go-i2p/go-sam-go"
     10 )
     11 
     12 type Node struct {
     13 	identity string
     14 	groups   []string
     15 }
     16 
     17 type Forward struct {
     18 	Name      string
     19 	KeyFile   string
     20 	LocalAddr net.Addr
     21 }
     22 
     23 func main() {
     24 	samAddr := "127.0.0.1:7656"
     25 	log.Println("Connecting to SAM server:", samAddr)
     26 	sam, err := sam3.NewSAM(samAddr)
     27 	if err != nil {
     28 		log.Fatal(err)
     29 	}
     30 
     31 	forwards := []Forward{
     32 		{
     33 			Name:      "navidrome",
     34 			KeyFile:   "navidrome.dat",
     35 			LocalAddr: &net.TCPAddr{IP: net.ParseIP("192.168.0.3"), Port: 4533},
     36 		},
     37 		{
     38 			Name:      "http8080",
     39 			KeyFile:   "http8080.dat",
     40 			LocalAddr: &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8080},
     41 		},
     42 	}
     43 
     44 	startServices(sam, forwards)
     45 	select {}
     46 }
     47 
     48 func startServices(sam *sam3.SAM, forwards []Forward) {
     49 	for _, fwd := range forwards {
     50 		keys, err := sam.EnsureKeyfile("keys/" + fwd.KeyFile)
     51 		if err != nil {
     52 			log.Printf("Failed to setup keys for %s: %v", fwd.Name, err)
     53 			continue
     54 		}
     55 
     56 		session, err := sam.NewStreamSession(fwd.Name+time.Now().Format("15:04:05"), keys, sam3.Options_Warning_ZeroHop)
     57 		if err != nil {
     58 			log.Printf("Failed to create session for %s: %v", fwd.Name, err)
     59 			continue
     60 		}
     61 
     62 		go func(target net.Addr, s *sam3.StreamSession) {
     63 			listener, err := s.Listen()
     64 			if err != nil {
     65 				log.Printf("Failed to listen for [%s]:%s", fwd.Name, err)
     66 			}
     67 			log.Printf("Service [%s] listening at %s", fwd.Name, keys.Addr().Base32())
     68 
     69 			for {
     70 				conn, err := listener.Accept()
     71 				if err != nil {
     72 					log.Println("accept error:", err)
     73 					continue
     74 				}
     75 				log.Printf("%s wants: %s", conn.RemoteAddr().String(), target)
     76 				go proxy(conn, target)
     77 			}
     78 		}(fwd.LocalAddr, session)
     79 	}
     80 }
     81 
     82 func proxy(i2pConn net.Conn, localAddr net.Addr) {
     83 	defer i2pConn.Close()
     84 
     85 	localConn, err := net.DialTimeout(localAddr.Network(), localAddr.String(), 5*time.Second)
     86 	if err != nil {
     87 		log.Printf("ERROR: Local dial failed: %v", err)
     88 		return
     89 	}
     90 	defer localConn.Close()
     91 
     92 	errChan := make(chan error, 2)
     93 
     94 	cp := func(dst io.Writer, src io.Reader) {
     95 		_, err := io.Copy(dst, src)
     96 		errChan <- err
     97 	}
     98 
     99 	go cp(localConn, i2pConn)
    100 	go cp(i2pConn, localConn)
    101 
    102 	<-errChan
    103 }