|
| 1 | +package client |
| 2 | + |
| 3 | +import ( |
| 4 | + "crypto" |
| 5 | + "crypto/rand" |
| 6 | + "crypto/rsa" |
| 7 | + "crypto/sha256" |
| 8 | + "encoding/binary" |
| 9 | + "fmt" |
| 10 | + "log" |
| 11 | + "net" |
| 12 | + "sync" |
| 13 | + "time" |
| 14 | + |
| 15 | + "github.com/songgao/water" |
| 16 | + "github.com/Azumi67/LocalTun_TCP/1.7/client/utils" |
| 17 | +) |
| 18 | + |
| 19 | +func RunClientSide(serverAddr string, serverPort int, tunIP, serverTunIP, subnetMask, tunName, privateKeyPath string, mtu int, sockEnabled bool, sockBuffSize int, keepaliveInterval time.Duration, tcpNoDelay, logEnabled bool, workerFlag string) { |
| 20 | + if subnetMask == "" { |
| 21 | + subnetMask = utils.DefaultSubnet(tunIP) |
| 22 | + } |
| 23 | + |
| 24 | + if logEnabled { |
| 25 | + logFile, err := utils.LogFile("/etc/client.log") |
| 26 | + if err != nil { |
| 27 | + log.Fatalf("Couldn't open log file: %v", err) |
| 28 | + } |
| 29 | + defer logFile.Close() |
| 30 | + log.SetOutput(logFile) |
| 31 | + } |
| 32 | + |
| 33 | + privateKey, err := utils.LoadPrivateKey(privateKeyPath) |
| 34 | + if err != nil { |
| 35 | + log.Fatalf("Couldn't load private key: %v", err) |
| 36 | + } |
| 37 | + |
| 38 | + config := water.Config{ |
| 39 | + DeviceType: water.TUN, |
| 40 | + } |
| 41 | + config.Name = tunName |
| 42 | + tun, err := water.New(config) |
| 43 | + if err != nil { |
| 44 | + log.Fatalf("Couldn't create TUN device: %v", err) |
| 45 | + } |
| 46 | + defer tun.Close() |
| 47 | + |
| 48 | + log.Printf("TUN device created: %s\n", tun.Name()) |
| 49 | + |
| 50 | + if err := utils.Cmd("ip", "link", "set", "dev", tun.Name(), "up"); err != nil { |
| 51 | + log.Fatalf("Couldn't bring up the TUN device: %v", err) |
| 52 | + } |
| 53 | + |
| 54 | + if err := utils.Cmd("ip", "link", "set", "dev", tun.Name(), "mtu", fmt.Sprintf("%d", mtu)); err != nil { |
| 55 | + log.Fatalf("Couldn't set MTU: %v", err) |
| 56 | + } |
| 57 | + |
| 58 | + if err := utils.Cmd("ip", "addr", "add", fmt.Sprintf("%s/%s", tunIP, subnetMask), "dev", tun.Name()); err != nil { |
| 59 | + log.Fatalf("Couldn't assign private IP address to TUN device: %v", err) |
| 60 | + } |
| 61 | + |
| 62 | + if utils.IPv6(serverTunIP) { |
| 63 | + if err := utils.Cmd("ip", "-6", "route", "add", fmt.Sprintf("%s/128", serverTunIP), "dev", tun.Name()); err != nil { |
| 64 | + log.Fatalf("Adding route for private IPv6 failed: %v", err) |
| 65 | + } |
| 66 | + } else { |
| 67 | + if err := utils.Cmd("ip", "route", "add", fmt.Sprintf("%s/32", serverTunIP), "dev", tun.Name()); err != nil { |
| 68 | + log.Fatalf("Adding route for private IPv4 failed: %v", err) |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + if err := utils.Cmd("sh", "-c", "echo 1 > /proc/sys/net/ipv4/ip_forward"); err != nil { |
| 73 | + log.Fatalf("Enabling IPv4 forwarding failed: %v", err) |
| 74 | + } |
| 75 | + if err := utils.Cmd("sh", "-c", "echo 1 > /proc/sys/net/ipv6/conf/all/forwarding"); err != nil { |
| 76 | + log.Fatalf("Enabling IPv6 forwarding failed: %v", err) |
| 77 | + } |
| 78 | + |
| 79 | + conn, err := net.Dial("tcp", fmt.Sprintf("[%s]:%d", serverAddr, serverPort)) |
| 80 | + if err != nil { |
| 81 | + log.Fatalf("Could not connect to server: %v", err) |
| 82 | + } |
| 83 | + defer conn.Close() |
| 84 | + |
| 85 | + log.Println("Connected to server") |
| 86 | + |
| 87 | + if keepaliveInterval > 0 { |
| 88 | + if tcpConn, ok := conn.(*net.TCPConn); ok { |
| 89 | + tcpConn.SetKeepAlive(true) |
| 90 | + tcpConn.SetKeepAlivePeriod(keepaliveInterval) |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + if sockEnabled && sockBuffSize > 0 { |
| 95 | + err := conn.(*net.TCPConn).SetReadBuffer(sockBuffSize) |
| 96 | + if err != nil { |
| 97 | + log.Printf("set read buffer size failed: %v", err) |
| 98 | + } |
| 99 | + err = conn.(*net.TCPConn).SetWriteBuffer(sockBuffSize) |
| 100 | + if err != nil { |
| 101 | + log.Printf("set write buffer size failed: %v", err) |
| 102 | + } |
| 103 | + } |
| 104 | + |
| 105 | + if tcpNoDelay { |
| 106 | + if tcpConn, ok := conn.(*net.TCPConn); ok { |
| 107 | + tcpConn.SetNoDelay(true) |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | + hashed := sha256.New() |
| 112 | + |
| 113 | + signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed.Sum(nil)) |
| 114 | + if err != nil { |
| 115 | + log.Fatalf("signing data wasn't possible: %v", err) |
| 116 | + } |
| 117 | + |
| 118 | + _, err = conn.Write(signature) |
| 119 | + if err != nil { |
| 120 | + log.Fatalf("Couldn't send auth key: %v", err) |
| 121 | + } |
| 122 | + |
| 123 | + workerCount := utils.WorkerCount(workerFlag) |
| 124 | + |
| 125 | + if workerCount > 0 { |
| 126 | + |
| 127 | + taskChan := make(chan []byte, workerCount) |
| 128 | + var workerWg sync.WaitGroup |
| 129 | + |
| 130 | + for i := 0; i < workerCount; i++ { |
| 131 | + workerWg.Add(1) |
| 132 | + go worker(tun, taskChan, &workerWg) |
| 133 | + } |
| 134 | + |
| 135 | + go func() { |
| 136 | + for { |
| 137 | + pcktLength := make([]byte, 2) |
| 138 | + _, err := conn.Read(pcktLength) |
| 139 | + if err != nil { |
| 140 | + continue |
| 141 | + } |
| 142 | + |
| 143 | + length := binary.BigEndian.Uint16(pcktLength) |
| 144 | + buff := make([]byte, length) |
| 145 | + n, err := conn.Read(buff) |
| 146 | + if err != nil { |
| 147 | + log.Printf("Couldn't read data from the server: %v", err) |
| 148 | + continue |
| 149 | + } |
| 150 | + |
| 151 | + if n != int(length) { |
| 152 | + log.Printf("Packet length mismatch: expected %d, but gotten %d", length, n) |
| 153 | + continue |
| 154 | + } |
| 155 | + |
| 156 | + taskChan <- buff[:n] |
| 157 | + } |
| 158 | + }() |
| 159 | + |
| 160 | + for { |
| 161 | + buff := make([]byte, 1500) |
| 162 | + n, err := tun.Read(buff) |
| 163 | + if err != nil { |
| 164 | + log.Printf("Couldn't read from TUN device: %v", err) |
| 165 | + continue |
| 166 | + } |
| 167 | + |
| 168 | + packet := make([]byte, 2+n) |
| 169 | + binary.BigEndian.PutUint16(packet[:2], uint16(n)) |
| 170 | + copy(packet[2:], buff[:n]) |
| 171 | + |
| 172 | + _, err = conn.Write(packet) |
| 173 | + if err != nil { |
| 174 | + log.Printf("Couldn't write to server: %v", err) |
| 175 | + continue |
| 176 | + } |
| 177 | + |
| 178 | + log.Printf("Forwarded %d bytes to the server\n", n) |
| 179 | + } |
| 180 | + |
| 181 | + close(taskChan) |
| 182 | + workerWg.Wait() |
| 183 | + } else { |
| 184 | + |
| 185 | + for { |
| 186 | + pcktLength := make([]byte, 2) |
| 187 | + _, err := conn.Read(pcktLength) |
| 188 | + if err != nil { |
| 189 | + continue |
| 190 | + } |
| 191 | + |
| 192 | + length := binary.BigEndian.Uint16(pcktLength) |
| 193 | + buff := make([]byte, length) |
| 194 | + n, err := conn.Read(buff) |
| 195 | + if err != nil { |
| 196 | + log.Printf("Couldn't read data from the server: %v", err) |
| 197 | + continue |
| 198 | + } |
| 199 | + |
| 200 | + if n != int(length) { |
| 201 | + log.Printf("Packet length mismatch: expected %d, but gotten %d", length, n) |
| 202 | + continue |
| 203 | + } |
| 204 | + |
| 205 | + _, err = tun.Write(buff[:n]) |
| 206 | + if err != nil { |
| 207 | + log.Printf("Couldn't write to TUN device: %v", err) |
| 208 | + continue |
| 209 | + } |
| 210 | + |
| 211 | + log.Printf("Written %d bytes to TUN device\n", n) |
| 212 | + } |
| 213 | + } |
| 214 | +} |
| 215 | + |
| 216 | +func worker(tun *water.Interface, taskChan <-chan []byte, wg *sync.WaitGroup) { |
| 217 | + defer wg.Done() |
| 218 | + for task := range taskChan { |
| 219 | + _, err := tun.Write(task) |
| 220 | + if err != nil { |
| 221 | + log.Printf("Couldn't write to TUN device: %v", err) |
| 222 | + continue |
| 223 | + } |
| 224 | + log.Printf("Worker task: written %d bytes to TUN device\n", len(task)) |
| 225 | + } |
| 226 | +} |
0 commit comments