func (s *RTcpForwardServer) connectRTcpForward(conn net.Conn, laddr, raddr net.Addr) error { glog.V(LINFO).Infof("[rtcp] %s - %s", laddr, raddr) req := gosocks5.NewRequest(gosocks5.CmdBind, ToSocksAddr(laddr)) if err := req.Write(conn); err != nil { glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err) return err } // first reply, bind status conn.SetReadDeadline(time.Now().Add(ReadTimeout)) rep, err := gosocks5.ReadReply(conn) if err != nil { glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err) return err } conn.SetReadDeadline(time.Time{}) if rep.Rep != gosocks5.Succeeded { glog.V(LWARNING).Infof("[rtcp] %s -> %s : bind on %s failure", laddr, raddr, laddr) return errors.New("Bind on " + laddr.String() + " failure") } glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr) // second reply, peer connection rep, err = gosocks5.ReadReply(conn) if err != nil { glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err) return err } if rep.Rep != gosocks5.Succeeded { glog.V(LWARNING).Infof("[rtcp] %s -> %s : peer connect failure", laddr, raddr) return errors.New("peer connect failure") } glog.V(LINFO).Infof("[rtcp] %s -> %s PEER %s CONNECTED", laddr, raddr, rep.Addr) go func() { defer conn.Close() lconn, err := net.DialTimeout("tcp", raddr.String(), time.Second*180) if err != nil { glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", rep.Addr, raddr, err) return } defer lconn.Close() glog.V(LINFO).Infof("[rtcp] %s <-> %s", rep.Addr, lconn.RemoteAddr()) s.Base.transport(lconn, conn) glog.V(LINFO).Infof("[rtcp] %s >-< %s", rep.Addr, lconn.RemoteAddr()) }() return nil }
func (s *UdpForwardServer) prepareUdpConnectTunnel(addr net.Addr) (net.Conn, error) { conn, err := s.Base.Chain.GetConn() if err != nil { return nil, err } conn.SetWriteDeadline(time.Now().Add(WriteTimeout)) if err = gosocks5.NewRequest(CmdUdpConnect, ToSocksAddr(addr)).Write(conn); err != nil { conn.Close() return nil, err } conn.SetWriteDeadline(time.Time{}) conn.SetReadDeadline(time.Now().Add(ReadTimeout)) reply, err := gosocks5.ReadReply(conn) if err != nil { conn.Close() return nil, err } conn.SetReadDeadline(time.Time{}) if reply.Rep != gosocks5.Succeeded { conn.Close() return nil, errors.New("failure") } return conn, nil }
func handleSocks5(conn net.Conn, methods []uint8) { if err := selectMethod(conn, methods...); err != nil { log.Println(err) return } req, err := gosocks5.ReadRequest(conn) if err != nil { return } //log.Println(req) sconn, err := makeTunnel() if err != nil { gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) log.Println(err) return } defer sconn.Close() switch req.Cmd { case gosocks5.CmdConnect, gosocks5.CmdBind: if err := req.Write(sconn); err != nil { return } Transport(conn, sconn) case gosocks5.CmdUdp: if err := req.Write(sconn); err != nil { return } rep, err := gosocks5.ReadReply(sconn) if err != nil || rep.Rep != gosocks5.Succeeded { return } uconn, err := net.ListenUDP("udp", nil) if err != nil { log.Println(err) gosocks5.NewReply(gosocks5.Failure, nil).Write(conn) return } defer uconn.Close() addr := ToSocksAddr(uconn.LocalAddr()) addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) log.Println("udp:", addr) rep = gosocks5.NewReply(gosocks5.Succeeded, addr) if err := rep.Write(conn); err != nil { log.Println(err) return } go cliTunnelUDP(uconn, sconn) // block, waiting for client exit ioutil.ReadAll(conn) } }
func connectSocks5Proxy(addr string) (conn net.Conn, err error) { conn, err = dial(proxyURL.Host) if err != nil { return } conf := &gosocks5.Config{ // Methods: []uint8{gosocks5.MethodNoAuth, gosocks5.MethodUserPass}, MethodSelected: proxyMethodSelected, } if proxyURL.User != nil { conf.Methods = []uint8{gosocks5.MethodUserPass} } c := gosocks5.ClientConn(conn, conf) if err := c.Handleshake(); err != nil { conn.Close() return nil, err } conn = c s := strings.Split(addr, ":") host := s[0] port := 80 if len(s) == 2 { n, _ := strconv.ParseUint(s[1], 10, 16) port = int(n) } a := &gosocks5.Addr{ Type: gosocks5.AddrDomain, Host: host, Port: uint16(port), } if err := gosocks5.NewRequest(gosocks5.CmdConnect, a).Write(conn); err != nil { conn.Close() return nil, err } rep, err := gosocks5.ReadReply(conn) if err != nil { conn.Close() return nil, err } if rep.Rep != gosocks5.Succeeded { conn.Close() return nil, errors.New("Socks Failture") } return conn, nil }
func requestSocks5(conn net.Conn, req *gosocks5.Request) (*gosocks5.Reply, error) { if err := req.Write(conn); err != nil { return nil, err } if glog.V(LDEBUG) { glog.Infoln(req.String()) } rep, err := gosocks5.ReadReply(conn) if err != nil { return nil, err } if glog.V(LDEBUG) { glog.Infoln(rep.String()) } return rep, nil }
func peekReply(dst io.Writer, src io.Reader) (rep *gosocks5.Reply, err error) { rep, err = gosocks5.ReadReply(src) if err != nil { glog.V(LWARNING).Infoln(err) rep = gosocks5.NewReply(gosocks5.Failure, nil) } if err = rep.Write(dst); err != nil { return } glog.V(LDEBUG).Infoln(rep) if rep.Rep != gosocks5.Succeeded { err = errors.New("Failure") } return }
func createServerConn(uconn *net.UDPConn, addr net.Addr) (c *UDPConn, err error) { if len(forwardArgs) == 0 { c = Server(uconn) return } fconn, _, err := forwardChain(forwardArgs...) if err != nil { if fconn != nil { fconn.Close() } return } glog.V(LINFO).Infoln("forward udp associate") req := gosocks5.NewRequest(gosocks5.CmdUdp, nil) if err = req.Write(fconn); err != nil { fconn.Close() return } glog.V(LDEBUG).Infoln(req) rep, err := gosocks5.ReadReply(fconn) if err != nil { fconn.Close() return } glog.V(LDEBUG).Infoln(rep) if rep.Rep != gosocks5.Succeeded { fconn.Close() return nil, errors.New("Failure") } glog.V(LINFO).Infoln("forward udp associate, on", rep.Addr, "OK") c = Server(fconn) return }
func handleShadow(conn net.Conn) { addr, extra, err := getShadowRequest(conn) if err != nil { log.Println(err) return } sconn, err := makeTunnel() if err != nil { log.Println(err) return } defer sconn.Close() req := gosocks5.NewRequest(gosocks5.CmdConnect, addr) if err := req.Write(sconn); err != nil { log.Println(err) return } rep, err := gosocks5.ReadReply(sconn) if err != nil || rep.Rep != gosocks5.Succeeded { log.Println(err) return } if extra != nil { if _, err := sconn.Write(extra); err != nil { log.Println(err) return } } if err := Transport(conn, sconn); err != nil { //log.Println(err) } }
func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) { bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String()) relay, err := net.ListenUDP("udp", bindAddr) // udp associate, strict mode: if the port already in use, it will return error if err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err) reply := gosocks5.NewReply(gosocks5.Failure, nil) reply.Write(s.conn) glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply) return } defer relay.Close() socksAddr := ToSocksAddr(relay.LocalAddr()) socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String()) reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr) if err := reply.Write(s.conn); err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err) return } glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), reply.Addr, reply) glog.V(LINFO).Infof("[socks5-udp] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), req.Addr, socksAddr) cc, err := s.Base.Chain.GetConn() // connection error if err != nil && err != ErrEmptyChain { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, err) return } // serve as standard socks5 udp relay local <-> remote if err == ErrEmptyChain { peer, er := net.ListenUDP("udp", nil) if er != nil { glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, er) return } defer peer.Close() go s.transportUDP(relay, peer) } // forward udp local <-> tunnel if err == nil { defer cc.Close() cc.SetWriteDeadline(time.Now().Add(WriteTimeout)) req := gosocks5.NewRequest(CmdUdpTun, nil) if err := req.Write(cc); err != nil { glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err) return } cc.SetWriteDeadline(time.Time{}) glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), req) cc.SetReadDeadline(time.Now().Add(ReadTimeout)) reply, err = gosocks5.ReadReply(cc) if err != nil { glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err) return } glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), reply) if reply.Rep != gosocks5.Succeeded { glog.V(LWARNING).Infoln("[socks5-udp] %s <- %s : udp associate failed", s.conn.RemoteAddr(), cc.RemoteAddr()) return } cc.SetReadDeadline(time.Time{}) glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr) go s.tunnelUDP(relay, cc, true) } glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr) b := make([]byte, SmallBufferSize) for { _, err := s.conn.Read(b) // discard any data from tcp connection if err != nil { glog.V(LWARNING).Infof("[socks5-udp] %s - %s : %s", s.conn.RemoteAddr(), socksAddr, err) break // client disconnected } } glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr) }
// Connect connect to addr through this proxy node func (c *ProxyConn) Connect(addr string) error { switch c.Node.Protocol { case "ss": // shadowsocks host, port, err := net.SplitHostPort(addr) if err != nil { return err } p, _ := strconv.Atoi(port) req := gosocks5.NewRequest(gosocks5.CmdConnect, &gosocks5.Addr{ Type: gosocks5.AddrDomain, Host: host, Port: uint16(p), }) buf := bytes.Buffer{} if err := req.Write(&buf); err != nil { return err } b := buf.Bytes() if _, err := c.Write(b[3:]); err != nil { return err } glog.V(LDEBUG).Infoln("[ss]", req) case "socks", "socks5": host, port, err := net.SplitHostPort(addr) if err != nil { return err } p, _ := strconv.Atoi(port) req := gosocks5.NewRequest(gosocks5.CmdConnect, &gosocks5.Addr{ Type: gosocks5.AddrDomain, Host: host, Port: uint16(p), }) if err := req.Write(c); err != nil { return err } glog.V(LDEBUG).Infoln("[socks5]", req) reply, err := gosocks5.ReadReply(c) if err != nil { return err } glog.V(LDEBUG).Infoln("[socks5]", reply) if reply.Rep != gosocks5.Succeeded { return errors.New("Service unavailable") } case "http": fallthrough default: req := &http.Request{ Method: http.MethodConnect, URL: &url.URL{Host: addr}, Host: addr, ProtoMajor: 1, ProtoMinor: 1, Header: make(http.Header), } req.Header.Set("Proxy-Connection", "keep-alive") if c.Node.User != nil { req.Header.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(c.Node.User.String()))) } if err := req.Write(c); err != nil { return err } if glog.V(LDEBUG) { dump, _ := httputil.DumpRequest(req, false) glog.Infoln(string(dump)) } resp, err := http.ReadResponse(bufio.NewReader(c), req) if err != nil { return err } if glog.V(LDEBUG) { dump, _ := httputil.DumpResponse(resp, false) glog.Infoln(string(dump)) } if resp.StatusCode != http.StatusOK { return errors.New(resp.Status) } } return nil }
func handleHttp(req *http.Request, conn net.Conn) { var host string var port uint16 if listenUrl != nil && listenUrl.User != nil { username := listenUrl.User.Username() password, _ := listenUrl.User.Password() if err := clientHttpAuth(req, conn, username, password); err != nil { log.Println(err) return } } s := strings.Split(req.Host, ":") host = s[0] port = 80 if len(s) == 2 { n, _ := strconv.ParseUint(s[1], 10, 16) port = uint16(n) } addr := &gosocks5.Addr{ Type: gosocks5.AddrDomain, Host: host, Port: port, } r := gosocks5.NewRequest(gosocks5.CmdConnect, addr) sconn, err := makeTunnel() if err != nil { conn.Write([]byte("HTTP/1.1 503 Service unavailable\r\n" + "Proxy-Agent: gost/" + Version + "\r\n\r\n")) log.Println(err) return } defer sconn.Close() if err := r.Write(sconn); err != nil { return } rep, err := gosocks5.ReadReply(sconn) if err != nil || rep.Rep != gosocks5.Succeeded { conn.Write([]byte("HTTP/1.1 503 Service unavailable\r\n" + "Proxy-Agent: gost/" + Version + "\r\n\r\n")) return } if req.Method == "CONNECT" { if _, err = conn.Write( []byte("HTTP/1.1 200 Connection established\r\n" + "Proxy-Agent: gost/" + Version + "\r\n\r\n")); err != nil { return } } else { if err := req.Write(sconn); err != nil { return } } if err := Transport(conn, sconn); err != nil { //log.Println(err) } }
func (s *RUdpForwardServer) connectRUdpForward(conn net.Conn, laddr, raddr *net.UDPAddr) error { glog.V(LINFO).Infof("[rudp] %s - %s", laddr, raddr) req := gosocks5.NewRequest(CmdUdpTun, ToSocksAddr(laddr)) conn.SetWriteDeadline(time.Now().Add(WriteTimeout)) if err := req.Write(conn); err != nil { glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err) return err } conn.SetWriteDeadline(time.Time{}) conn.SetReadDeadline(time.Now().Add(ReadTimeout)) rep, err := gosocks5.ReadReply(conn) if err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return err } conn.SetReadDeadline(time.Time{}) if rep.Rep != gosocks5.Succeeded { glog.V(LWARNING).Infof("[rudp] %s <- %s : bind on %s failure", laddr, raddr, laddr) return errors.New(fmt.Sprintf("bind on %s failure", laddr)) } glog.V(LINFO).Infof("[rudp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr) for { dgram, err := gosocks5.ReadUDPDatagram(conn) if err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return err } go func() { b := make([]byte, MediumBufferSize) relay, err := net.DialUDP("udp", nil, raddr) if err != nil { glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err) return } defer relay.Close() if _, err := relay.Write(dgram.Data); err != nil { glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err) return } glog.V(LDEBUG).Infof("[rudp] %s >>> %s length: %d", laddr, raddr, len(dgram.Data)) relay.SetReadDeadline(time.Now().Add(ReadTimeout)) n, err := relay.Read(b) if err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return } relay.SetReadDeadline(time.Time{}) glog.V(LDEBUG).Infof("[rudp] %s <<< %s length: %d", laddr, raddr, n) conn.SetWriteDeadline(time.Now().Add(WriteTimeout)) if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(conn); err != nil { glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err) return } conn.SetWriteDeadline(time.Time{}) }() } }