// dial tcp with tcp fastopen // 第一个包体积不要太大,需要小于一定数量,否则会被吃掉(正确性问题), // 如果过大,此处会在连接时发送前一部分,连接后又发送一部分 func TfoDial(nextAddr string, data []byte) (conn net.Conn, err error) { s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) if err != nil { return nil, err } defer unix.Close(s) sa, err := kmgUnix.IPv4TcpAddrToUnixSocksAddr(nextAddr) if err != nil { return nil, err } if len(data) <= tfoFirstSize { err = unix.Sendto(s, data, unix.MSG_FASTOPEN, sa) if err != nil { return } } else { err = unix.Sendto(s, data[:tfoFirstSize], unix.MSG_FASTOPEN, sa) if err != nil { return } } f := os.NewFile(uintptr(s), "TFODial") defer f.Close() conn, err = net.FileConn(f) if err != nil { return } if len(data) > tfoFirstSize { _, err = conn.Write(data[tfoFirstSize:]) if err != nil { return nil, err } } return conn, nil }
// TcpListen is listening for incoming IP packets which are being intercepted. // In conflict to regular Listen mehtod the socket destination and source addresses // are of the intercepted connection. // Else then that it works exactly like net package net.Listen. func TcpListen(listenAddr string) (listener net.Listener, err error) { s, err := unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, 0) if err != nil { return nil, err } defer unix.Close(s) err = unix.SetsockoptInt(s, unix.SOL_IP, unix.IP_TRANSPARENT, 1) if err != nil { return nil, err } sa, err := IPv6TcpAddrToUnixSocksAddr(listenAddr) if err != nil { return nil, err } err = unix.Bind(s, sa) if err != nil { return nil, err } err = unix.Listen(s, unix.SOMAXCONN) if err != nil { return nil, err } f := os.NewFile(uintptr(s), "TProxy") defer f.Close() return net.FileListener(f) }
//network is useless ,it will always use tcp4 func TfoListen(network string, listenAddr string) (listener net.Listener, err error) { s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0) if err != nil { return nil, err } defer unix.Close(s) err = unix.SetsockoptInt(s, unix.SOL_TCP, 23, 10) if err != nil { return nil, err } err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) if err != nil { return nil, err } sa, err := kmgUnix.IPv4TcpAddrToUnixSocksAddr(listenAddr) if err != nil { return nil, err } err = unix.Bind(s, sa) if err != nil { return nil, err } err = unix.Listen(s, 10) if err != nil { return nil, err } f := os.NewFile(uintptr(s), "TFOListen") defer f.Close() return net.FileListener(f) }
// NewSocket returns a HCI User Channel of specified device id. // If id is -1, the first available HCI device is returned. func NewSocket(id int) (*Socket, error) { var err error // Create RAW HCI Socket. fd, err := unix.Socket(unix.AF_BLUETOOTH, unix.SOCK_RAW, unix.BTPROTO_HCI) if err != nil { return nil, errors.Wrap(err, "can't create socket") } if id != -1 { return open(fd, id) } req := devListRequest{devNum: hciMaxDevices} if err = ioctl(uintptr(fd), hciGetDeviceList, uintptr(unsafe.Pointer(&req))); err != nil { return nil, errors.Wrap(err, "can't get device list") } var msg string for id := 0; id < int(req.devNum); id++ { s, err := open(fd, id) if err == nil { return s, nil } msg = msg + fmt.Sprintf("(hci%d: %s)", id, err) } return nil, errors.Errorf("no devices available: %s", msg) }
// TfoListen announces on the local network address laddr using tcp protocol and fast open option. // laddr must be in the form of "host:port". // It returns a tfo-enabled listener and an error if any. func tfoListen(laddr string) (lst net.Listener, err error) { s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0) if err != nil { return } defer unix.Close(s) sa, err := tcpAddrToSockaddr(laddr) if err != nil { return } err = unix.Bind(s, sa) if err != nil { return } // set the socket to fast open mode err = unix.SetsockoptInt(s, unix.SOL_TCP, 23, TCP_FASTOPEN_VAL) if err != nil { return } err = unix.Listen(s, 10) if err != nil { return } f := os.NewFile(uintptr(s), "TFOListen") defer f.Close() return net.FileListener(f) }
func UdpTProxyConn(listenAddr string) (udp *net.UDPConn, err error) { var c net.Conn s, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0) if err != nil { return nil, err } //Why close here ??? defer unix.Close(s) err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) if err != nil { return nil, err } err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_BROADCAST, 1) if err != nil { return nil, err } err = unix.SetsockoptInt(s, unix.SOL_IP, unix.IP_TRANSPARENT, 1) if err != nil { return nil, err } err = unix.SetsockoptInt(s, unix.IPPROTO_IP, unix.IP_RECVORIGDSTADDR, 1) if err != nil { return nil, err } sa, err := IPv6TcpAddrToUnixSocksAddr(listenAddr) if err != nil { return nil, err } err = unix.Bind(s, sa) if err != nil { return nil, err } f := os.NewFile(uintptr(s), "TProxy") defer f.Close() c, err = net.FileConn(f) if err != nil { return nil, err } var ok bool if udp, ok = c.(*net.UDPConn); ok { return } else { c.Close() return nil, errors.New("type error") } }
func newDev(ifce *net.Interface, frameFilter FrameFilter) (dev Dev, err error) { d := new(afpacket) d.ifce = ifce d.filter = frameFilter d.fd, err = unix.Socket(unix.AF_PACKET, unix.SOCK_RAW, htons(unix.ETH_P_ALL)) if err != nil { return } d.sockaddrLL = new(unix.SockaddrLinklayer) d.sockaddrLL.Ifindex = ifce.Index d.sockaddrLL.Halen = 6 dev = d return }
func NewPacketSock(ifindex int) (*packetSock, error) { fd, err := unix.Socket(unix.AF_PACKET, unix.SOCK_DGRAM, int(swap16(unix.ETH_P_IP))) if err != nil { return nil, err } addr := unix.SockaddrLinklayer{ Ifindex: ifindex, Protocol: swap16(unix.ETH_P_IP), } if err = unix.Bind(fd, &addr); err != nil { return nil, err } return &packetSock{ fd: fd, ifindex: ifindex, }, nil }
// TfoDial dials to addr using tcp protocol with fast open option set, // addr should be in the form of "addr:port", // the data is sent along with the first syn packet of tcp handshake. // It returns a established connection and an error if any. func tfoDial(addr string, data []byte) (conn net.Conn, err error) { fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) if err != nil { return } defer unix.Close(fd) sa, err := tcpAddrToSockaddr(addr) if err != nil { return } err = unix.Sendto(fd, data, unix.MSG_FASTOPEN, sa) if err != nil { return } f := os.NewFile(uintptr(fd), "TFODial") defer f.Close() return net.FileConn(f) }
// see also https://github.com/jbenet/go-reuseport/blob/master/impl_unix.go#L279 func NewSocket(addr *net.UDPAddr, recvBuf int) (net.PacketConn, error) { sockFD, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM|syscall.SOCK_CLOEXEC|syscall.SOCK_NONBLOCK, 0) if err != nil { return nil, err } // unix.SO_REUSEPORT is not defined on linux 386/amd64, see // https://github.com/golang/go/issues/16075 if err := unix.SetsockoptInt(sockFD, unix.SOL_SOCKET, 0xf, 1); err != nil { return nil, err } if err := unix.SetsockoptInt(sockFD, unix.SOL_SOCKET, unix.SO_RCVBUF, recvBuf); err != nil { return nil, err } sockaddr := unix.SockaddrInet4{ Port: addr.Port, } if copied := copy(sockaddr.Addr[:], addr.IP); copied != net.IPv4len { panic("did not copy enough bytes of ip address") } if err := unix.Bind(sockFD, &sockaddr); err != nil { return nil, err } osFD := os.NewFile(uintptr(sockFD), "veneursock") // this will close the FD we passed to NewFile defer osFD.Close() // however, FilePacketConn duplicates the FD, so closing the File's FD does // not affect this object's FD ret, err := net.FilePacketConn(osFD) if err != nil { return nil, err } return ret, nil }
func main() { fmt.Println("Listening on port :", port) counter := new(connCounter) // create socket fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) if err != nil { log.Fatal("socket-error: ", err) } // sa struct sa := new(unix.SockaddrInet4) sa.Port = 9090 // bind err = unix.Bind(fd, sa) if err != nil { log.Fatal("bind: ", err) } // listen err = unix.Listen(fd, 3) if err != nil { log.Fatal("listen: ", err) } for { connInfo := new(connection) // accept connection, discard SA struct newFd, _, err := unix.Accept(fd) connInfo.fd = newFd if err != nil { log.Fatal("accept: ", err) } // client reads until closes, adding // a gorutine allows dealing with more // requests. counter.mu.Lock() counter.num += 1 counter.mu.Unlock() fmt.Println("Number of connections: ", counter.num) go func(c *connection, counter *connCounter) { fmt.Printf("Conn.fd=%d\n", c.fd) for { // read c.buf = make([]byte, 50) n, err := unix.Read(c.fd, c.buf) if err != nil { log.Fatal("read: ", err) } fmt.Printf("Read: %d Value: %s\n", n, string(c.buf[0:n])) // close if string(c.buf[0:5]) == "close" { _, err = unix.Write(c.fd, []byte(`Bye bye buddy`)) if err != nil { log.Fatal("close: ", err) } err = unix.Close(c.fd) if err != nil { log.Fatal("close: ", err) } counter.mu.Lock() counter.num = counter.num - 1 counter.mu.Unlock() return } } }(connInfo, counter) } }
// TcpDial is a special tcp connection which binds a non local address as the source. // Except then the option to bind to a specific local address which the machine doesn't posses // it is exactly like any other net.Conn connection. // It is advised to use port numbered 0 in the localAddr and leave the kernel to choose which // Local port to use in order to avoid errors and binding conflicts. func TcpDial(localAddr, remoteAddr string) (conn net.Conn, err error) { fmt.Println(localAddr) fmt.Println(remoteAddr) s, err := unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, 0) //In a case there was a need for a non-blocking socket an example //s, err := unix.Socket(unix.AF_INET6, unix.SOCK_STREAM |unix.SOCK_NONBLOCK, 0) if err != nil { fmt.Println(err) return nil, err } defer unix.Close(s) err = unix.SetsockoptInt(s, unix.SOL_IP, unix.IP_TRANSPARENT, 1) if err != nil { fmt.Println(err) return nil, err } err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) if err != nil { fmt.Println(err) return nil, err } rhost, rport, err := net.SplitHostPort(localAddr) _ = rport if err != nil { fmt.Fprintln(os.Stderr, err) } sa, err := IPv6TcpAddrToUnixSocksAddr(rhost + ":0") if err != nil { fmt.Println(err) return nil, err } remoteSocket, err := IPv6TcpAddrToUnixSocksAddr(remoteAddr) if err != nil { fmt.Println(err) return nil, err } err = unix.Bind(s, sa) if err != nil { fmt.Println(err) return nil, err } err = unix.Connect(s, remoteSocket) if err != nil { fmt.Println(err) return nil, err } f := os.NewFile(uintptr(s), "TProxyTcpClient") client, err := net.FileConn(f) if err != nil { fmt.Println(err) return nil, err } fmt.Println(client.LocalAddr()) fmt.Println(client.RemoteAddr()) return client, err }