diff --git a/common/cache/cache.go b/common/cache/cache.go index d8a37ab..4f6033c 100644 --- a/common/cache/cache.go +++ b/common/cache/cache.go @@ -6,8 +6,10 @@ import ( "github.com/patrickmn/go-cache" ) +// The global cache var _cache = cache.New(30*time.Minute, 10*time.Minute) +// GetCache returns the cache func GetCache() *cache.Cache { return _cache } diff --git a/common/cipher/cipher.go b/common/cipher/cipher.go index e1012c5..4df7742 100644 --- a/common/cipher/cipher.go +++ b/common/cipher/cipher.go @@ -1,11 +1,14 @@ package cipher +// The default key var _key = []byte("vtun@2022") +// SetKey sets the key func SetKey(key string) { _key = []byte(key) } +// XOR encrypts the data func XOR(src []byte) []byte { _klen := len(_key) for i := 0; i < len(src); i++ { diff --git a/common/config/config.go b/common/config/config.go index 205a8ca..2076cb3 100644 --- a/common/config/config.go +++ b/common/config/config.go @@ -1,5 +1,6 @@ package config +// The config struct type Config struct { DeviceName string LocalAddr string diff --git a/common/counter/counter.go b/common/counter/counter.go index 91da45d..635bc0c 100644 --- a/common/counter/counter.go +++ b/common/counter/counter.go @@ -2,21 +2,28 @@ package counter import "sync/atomic" +// totalReadBytes is the total number of bytes read var _totalReadBytes uint64 = 0 + +// totalWrittenBytes is the total number of bytes written var _totalWrittenBytes uint64 = 0 +// IncrReadBytes increments the number of bytes read func IncrReadBytes(n int) { atomic.AddUint64(&_totalReadBytes, uint64(n)) } +//IncrWrittenBytes increments the number of bytes written func IncrWrittenBytes(n int) { atomic.AddUint64(&_totalWrittenBytes, uint64(n)) } +// GetReadBytes returns the number of bytes read func GetReadBytes() uint64 { return _totalReadBytes } +// GetWrittenBytes returns the number of bytes written func GetWrittenBytes() uint64 { return _totalWrittenBytes } diff --git a/common/netutil/netutil.go b/common/netutil/netutil.go index 28d47e0..b5f0994 100644 --- a/common/netutil/netutil.go +++ b/common/netutil/netutil.go @@ -15,6 +15,7 @@ import ( "github.com/net-byte/vtun/common/config" ) +// ConnectServer connects to the server with the given address. func ConnectServer(config config.Config) net.Conn { net.DefaultResolver = &net.Resolver{ PreferGo: true, @@ -47,6 +48,7 @@ func ConnectServer(config config.Config) net.Conn { return c } +// GetInterfaceName returns the name of interface func GetInterface() (name string) { ifaces := getAllInterfaces() if len(ifaces) == 0 { @@ -63,6 +65,7 @@ func GetInterface() (name string) { return name } +// getAllInterfaces returns all interfaces func getAllInterfaces() []net.Interface { ifaces, err := net.Interfaces() if err != nil { @@ -82,6 +85,7 @@ func getAllInterfaces() []net.Interface { return outInterfaces } +// isPhysicalInterface returns true if the interface is physical func isPhysicalInterface(addr string) bool { prefixArray := []string{"ens", "enp", "enx", "eno", "eth", "en0", "wlan", "wlp", "wlo", "wlx", "wifi0", "lan0"} for _, pref := range prefixArray { @@ -92,6 +96,7 @@ func isPhysicalInterface(addr string) bool { return false } +// Lookup IP address of the given hostname func LookupIP(domain string) net.IP { ips, err := net.LookupIP(domain) if err != nil || len(ips) == 0 { @@ -101,32 +106,39 @@ func LookupIP(domain string) net.IP { return ips[0] } +// IsIPv4 returns true if the packet is IPv4s func IsIPv4(packet []byte) bool { flag := packet[0] >> 4 return flag == 4 } +// IsIPv6 returns true if the packet is IPv6s func IsIPv6(packet []byte) bool { flag := packet[0] >> 4 return flag == 6 } +// GetIPv4Src returns the IPv4 source address of the packet func GetIPv4Src(packet []byte) net.IP { return net.IPv4(packet[12], packet[13], packet[14], packet[15]) } +// GEtIPv4Dst returns the IPv4 destination address of the packet func GetIPv4Dst(packet []byte) net.IP { return net.IPv4(packet[16], packet[17], packet[18], packet[19]) } +// GetIPv6Src returns the IPv6 source address of the packet func GetIPv6Src(packet []byte) net.IP { return net.IP(packet[8:24]) } +// GetIPv6Dst returns the IPv6 destination address of the packet func GetIPv6Dst(packet []byte) net.IP { return net.IP(packet[24:40]) } +// GetSrcKey returns the source key of the packet func GetSrcKey(packet []byte) string { key := "" if IsIPv4(packet) && len(packet) >= 20 { @@ -137,6 +149,7 @@ func GetSrcKey(packet []byte) string { return key } +// GetdstKey returns the destination key of the packets func GetDstKey(packet []byte) string { key := "" if IsIPv4(packet) && len(packet) >= 20 { @@ -147,6 +160,7 @@ func GetDstKey(packet []byte) string { return key } +// ExecuteCommand executes the given command func ExecCmd(c string, args ...string) string { log.Printf("exec cmd: %v %v:", c, args) cmd := exec.Command(c, args...) @@ -161,6 +175,7 @@ func ExecCmd(c string, args ...string) string { return strings.ReplaceAll(s, "\n", "") } +// GetLocalGatewayOnLinux returns the local gateway IP address on Linux func GetLocalGatewayOnLinux(ipv4 bool) string { if ipv4 { return ExecCmd("sh", "-c", "route -n | grep 'UG[ \t]' | awk 'NR==1{print $2}'") @@ -168,6 +183,7 @@ func GetLocalGatewayOnLinux(ipv4 bool) string { return ExecCmd("sh", "-c", "route -6 -n | grep 'UG[ \t]' | awk 'NR==1{print $2}'") } +// GetLocalGatewayOnMac returns the local gateway IP address on MacOS func GetLocalGatewayOnMac(ipv4 bool) string { if ipv4 { return ExecCmd("sh", "-c", "route -n get default | grep 'gateway' | awk 'NR==1{print $2}'") diff --git a/grpc/grpcclient.go b/grpc/grpcclient.go index d46f62a..41c9d78 100644 --- a/grpc/grpcclient.go +++ b/grpc/grpcclient.go @@ -17,6 +17,7 @@ import ( "github.com/songgao/water" ) +// StartClient starts the grpc client func StartClient(config config.Config) { log.Printf("vtun grpc client started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -47,6 +48,7 @@ func StartClient(config config.Config) { } } +// tunToGrpc sends packets from tun to grpc func tunToGrpc(config config.Config, iface *water.Interface) { packet := make([]byte, config.MTU) for { @@ -68,6 +70,7 @@ func tunToGrpc(config config.Config, iface *water.Interface) { } } +// grpcToTun sends packets from grpc to tun func grpcToTun(config config.Config, stream proto.GrpcServe_TunnelClient, iface *water.Interface) { for { packet, err := stream.Recv() diff --git a/grpc/grpcserver.go b/grpc/grpcserver.go index d63d4cd..2d6db10 100644 --- a/grpc/grpcserver.go +++ b/grpc/grpcserver.go @@ -17,17 +17,20 @@ import ( "github.com/songgao/water" ) +// The StreamService is the implementation of the StreamServer interface type StreamService struct { proto.UnimplementedGrpcServeServer config config.Config iface *water.Interface } +// Tunnel implements the StreamServer interface func (s *StreamService) Tunnel(srv proto.GrpcServe_TunnelServer) error { toServer(srv, s.config, s.iface) return nil } +// StartServer starts the grpc server func StartServer(config config.Config) { log.Printf("vtun grpc server started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -49,6 +52,7 @@ func StartServer(config config.Config) { } } +// toClient sends packets from tun to grpc func toClient(config config.Config, iface *water.Interface) { packet := make([]byte, config.MTU) for { @@ -68,6 +72,7 @@ func toClient(config config.Config, iface *water.Interface) { } } +// toServer sends packets from grpc to tun func toServer(srv proto.GrpcServe_TunnelServer, config config.Config, iface *water.Interface) { for { packet, err := srv.Recv() diff --git a/main.go b/main.go index 9e0520c..842903a 100644 --- a/main.go +++ b/main.go @@ -52,6 +52,7 @@ func main() { stopApp(config) } +// initConfig initializes the config func initConfig(config *config.Config) { if !config.ServerMode && config.GlobalMode { host, _, err := net.SplitHostPort(config.ServerAddr) @@ -71,6 +72,7 @@ func initConfig(config *config.Config) { log.Printf("init config:%s", string(json)) } +// startApp starts the app func startApp(config config.Config) { switch config.Protocol { case "udp": @@ -106,7 +108,8 @@ func startApp(config config.Config) { } } +// stopApp stops the app func stopApp(config config.Config) { - tun.Reset(config) - log.Printf("stopped!!!") + tun.ResetTun(config) + log.Printf("vtun stopped") } diff --git a/register/register.go b/register/register.go index 29adf7c..76fd6f6 100644 --- a/register/register.go +++ b/register/register.go @@ -9,25 +9,30 @@ import ( "github.com/patrickmn/go-cache" ) +// The global cache for register var _register *cache.Cache func init() { _register = cache.New(30*time.Minute, 3*time.Minute) } +// AddClientIP adds a client ip to the register func AddClientIP(ip string) { _register.Add(ip, 0, cache.DefaultExpiration) } +// DeleteClientIP deletes a client ip from the register func DeleteClientIP(ip string) { _register.Delete(ip) } +// ExistClientIP checks if the client ip is in the register func ExistClientIP(ip string) bool { _, ok := _register.Get(ip) return ok } +// keepAlive keeps the client ip alive func KeepAliveClientIP(ip string) { if ExistClientIP(ip) { _register.Increment(ip, 1) @@ -36,6 +41,7 @@ func KeepAliveClientIP(ip string) { } } +// PickClientIP picks a client ip from the register func PickClientIP(cidr string) (clientIP string, prefixLength string) { ip, ipNet, err := net.ParseCIDR(cidr) if err != nil { @@ -59,7 +65,8 @@ func PickClientIP(cidr string) (clientIP string, prefixLength string) { return "", "" } -func ListClientIP() []string { +// ListClientIPs returns the client ips in the register +func ListClientIPs() []string { result := []string{} for k := range _register.Items() { result = append(result, k) @@ -67,11 +74,13 @@ func ListClientIP() []string { return result } +// addressCount returns the number of addresses in a CIDR network. func addressCount(network *net.IPNet) uint64 { prefixLen, bits := network.Mask.Size() return 1 << (uint64(bits) - uint64(prefixLen)) } +// incr increments the ip by 1 func incr(IP net.IP) net.IP { IP = checkIPv4(IP) incIP := make([]byte, len(IP)) @@ -85,6 +94,7 @@ func incr(IP net.IP) net.IP { return incIP } +// checkIPv4 checks if the ip is IPv4 func checkIPv4(ip net.IP) net.IP { if v4 := ip.To4(); v4 != nil { return v4 diff --git a/tls/tlsclient.go b/tls/tlsclient.go index 435f308..64ffa29 100644 --- a/tls/tlsclient.go +++ b/tls/tlsclient.go @@ -14,7 +14,7 @@ import ( "github.com/songgao/water" ) -// Start tls client +// StartClient starts the tls client func StartClient(config config.Config) { log.Printf("vtun tls client started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -37,6 +37,7 @@ func StartClient(config config.Config) { } } +// tunToTLS sends packets from tun to tls func tunToTLS(config config.Config, iface *water.Interface) { packet := make([]byte, config.MTU) for { @@ -59,6 +60,7 @@ func tunToTLS(config config.Config, iface *water.Interface) { } } +// tlsToTun sends packets from tls to tun func tlsToTun(config config.Config, tlsconn net.Conn, iface *water.Interface) { defer tlsconn.Close() packet := make([]byte, config.MTU) diff --git a/tls/tlsserver.go b/tls/tlsserver.go index f0c2007..c8bb8df 100644 --- a/tls/tlsserver.go +++ b/tls/tlsserver.go @@ -15,7 +15,7 @@ import ( "github.com/songgao/water" ) -//Start tls server +// StartServer starts the tls server func StartServer(config config.Config) { log.Printf("vtun tls server started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -51,6 +51,7 @@ func StartServer(config config.Config) { } } +// toClient sends packets from iface to tlsconn func toClient(config config.Config, iface *water.Interface) { packet := make([]byte, config.MTU) for { @@ -70,7 +71,7 @@ func toClient(config config.Config, iface *water.Interface) { } } -// todo fallback to http +// toServer sends packets from tlsconn to iface func toServer(config config.Config, tlsconn net.Conn, iface *water.Interface) { defer tlsconn.Close() packet := make([]byte, config.MTU) diff --git a/tun/tun.go b/tun/tun.go index 1ff123e..0f5fb2b 100644 --- a/tun/tun.go +++ b/tun/tun.go @@ -11,6 +11,7 @@ import ( "github.com/songgao/water" ) +// CreateTun creates a tun interface func CreateTun(config config.Config) (iface *water.Interface) { c := water.Config{DeviceType: water.TUN} if config.DeviceName != "" { @@ -25,6 +26,7 @@ func CreateTun(config config.Config) (iface *water.Interface) { return iface } +// ConfigTun configures the tun interface func configTun(config config.Config, iface *water.Interface) { os := runtime.GOOS ip, _, err := net.ParseCIDR(config.CIDR) @@ -91,7 +93,8 @@ func configTun(config config.Config, iface *water.Interface) { } } -func Reset(config config.Config) { +// ResetTun resets the tun interface +func ResetTun(config config.Config) { os := runtime.GOOS if os == "darwin" && !config.ServerMode && config.GlobalMode { netutil.ExecCmd("route", "add", "default", config.LocalGateway) diff --git a/udp/udpclient.go b/udp/udpclient.go index 2ab6726..5e93797 100644 --- a/udp/udpclient.go +++ b/udp/udpclient.go @@ -12,7 +12,7 @@ import ( "golang.org/x/net/ipv6" ) -// Start udp client +// StartClient starts the udp client func StartClient(config config.Config) { log.Printf("vtun udp client started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -45,6 +45,7 @@ func StartClient(config config.Config) { c.tunToUdp() } +// The client struct type Client struct { config config.Config iface *water.Interface @@ -52,6 +53,7 @@ type Client struct { serverAddr *net.UDPAddr } +// udpToTun sends packets from udp to tun func (c *Client) udpToTun() { packet := make([]byte, c.config.MTU) for { @@ -66,6 +68,8 @@ func (c *Client) udpToTun() { c.iface.Write(b) } } + +// tunToUdp sends packets from tun to udp func (c *Client) tunToUdp() { packet := make([]byte, c.config.MTU) for { diff --git a/udp/udpserver.go b/udp/udpserver.go index 781e5dc..289a8bb 100644 --- a/udp/udpserver.go +++ b/udp/udpserver.go @@ -15,7 +15,7 @@ import ( "golang.org/x/net/ipv6" ) -// Start udp server +// StartServer starts the udp server func StartServer(config config.Config) { log.Printf("vtun udp server started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -44,6 +44,7 @@ func StartServer(config config.Config) { s.udpToTun() } +// the server struct type Server struct { config config.Config iface *water.Interface @@ -51,6 +52,7 @@ type Server struct { connCache *cache.Cache } +// tunToUdp sends packets from tun to udp func (s *Server) tunToUdp() { packet := make([]byte, s.config.MTU) for { @@ -70,6 +72,7 @@ func (s *Server) tunToUdp() { } } +// udpToTun sends packets from udp to tun func (s *Server) udpToTun() { packet := make([]byte, s.config.MTU) for { diff --git a/ws/wsclient.go b/ws/wsclient.go index 892b9fe..175a26b 100644 --- a/ws/wsclient.go +++ b/ws/wsclient.go @@ -14,7 +14,7 @@ import ( "github.com/songgao/water" ) -// Start websocket client +// StartClient starts the ws client func StartClient(config config.Config) { log.Printf("vtun websocket client started on %v", config.LocalAddr) iface := tun.CreateTun(config) @@ -31,6 +31,7 @@ func StartClient(config config.Config) { } } +// wsToTun sends packets from ws to tun func wsToTun(config config.Config, wsconn net.Conn, iface *water.Interface) { defer wsconn.Close() for { @@ -49,6 +50,7 @@ func wsToTun(config config.Config, wsconn net.Conn, iface *water.Interface) { } } +// tunToWs sends packets from tun to ws func tunToWs(config config.Config, iface *water.Interface) { packet := make([]byte, config.MTU) for { diff --git a/ws/wsserver.go b/ws/wsserver.go index a1b0db2..a21436f 100644 --- a/ws/wsserver.go +++ b/ws/wsserver.go @@ -22,7 +22,7 @@ import ( "github.com/songgao/water" ) -// Start websocket server +// StartServer starts the ws server func StartServer(config config.Config) { iface := tun.CreateTun(config) // server -> client @@ -88,7 +88,7 @@ func StartServer(config config.Config) { if !checkPermission(w, r, config) { return } - io.WriteString(w, strings.Join(register.ListClientIP(), "\r\n")) + io.WriteString(w, strings.Join(register.ListClientIPs(), "\r\n")) }) http.HandleFunc("/register/prefix/ipv4", func(w http.ResponseWriter, r *http.Request) { @@ -132,6 +132,8 @@ func StartServer(config config.Config) { } } + +// checkPermission checks the permission of the request func checkPermission(w http.ResponseWriter, req *http.Request, config config.Config) bool { key := req.Header.Get("key") if key != config.Key { @@ -142,6 +144,7 @@ func checkPermission(w http.ResponseWriter, req *http.Request, config config.Con return true } +// toClient sends data to client func toClient(config config.Config, iface *water.Interface) { packet := make([]byte, config.MTU) for { @@ -162,6 +165,7 @@ func toClient(config config.Config, iface *water.Interface) { } } +// toServer sends data to server func toServer(config config.Config, wsconn net.Conn, iface *water.Interface) { defer wsconn.Close() for {