Created
July 29, 2019 02:15
-
-
Save kallydev/f823fd551f4bd984fbf53b5704a5b588 to your computer and use it in GitHub Desktop.
Simple TCP forwarding implementation, part of the code comes from shadowsocks/shadowsocks-go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/shadowsocks/shadowsocks-go/blob/master/LICENSE | |
package main | |
type LeakyBuf struct { | |
bufSize int | |
freeList chan []byte | |
} | |
const leakyBufSize = 4096 | |
const maxNBuf = 2048 | |
var leakyBuf = NewLeakyBuf(maxNBuf, leakyBufSize) | |
func NewLeakyBuf(n, bufSize int) *LeakyBuf { | |
return &LeakyBuf{ | |
bufSize: bufSize, | |
freeList: make(chan []byte, n), | |
} | |
} | |
func (lb *LeakyBuf) Get() (b []byte) { | |
select { | |
case b = <-lb.freeList: | |
default: | |
b = make([]byte, lb.bufSize) | |
} | |
return | |
} | |
func (lb *LeakyBuf) Put(b []byte) { | |
if len(b) != lb.bufSize { | |
panic("invalid buffer size that's put into leaky buffer") | |
} | |
select { | |
case lb.freeList <- b: | |
default: | |
} | |
return | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"log" | |
"net" | |
) | |
var localAddr, remoteAddr string | |
func main() { | |
flag.StringVar(&localAddr, "l", "0.0.0.0:80", "local addr") | |
flag.StringVar(&remoteAddr, "r", "127.0.0.1:8080", "remote addr") | |
flag.Parse() | |
tcpAddr, err := net.ResolveTCPAddr("tcp", localAddr) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
tcpListener, err := net.ListenTCP("tcp", tcpAddr) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
for { | |
tcpConn, err := tcpListener.AcceptTCP() | |
if err != nil { | |
log.Println(err) | |
continue | |
} | |
go tcpHandler(tcpConn) | |
} | |
} | |
func tcpHandler(tcpConn *net.TCPConn) { | |
dstConn, err := net.Dial("tcp", remoteAddr) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
go pipe(tcpConn, dstConn) | |
pipe(dstConn, tcpConn) | |
} | |
func pipe(src, dst net.Conn) { | |
defer dst.Close() | |
buf := leakyBuf.Get() | |
defer leakyBuf.Put(buf) | |
for { | |
n, err := src.Read(buf) | |
if n > 0 { | |
if _, err := dst.Write(buf[0:n]); err != nil { | |
log.Println(err) | |
break | |
} | |
} | |
if err != nil { | |
break | |
} | |
} | |
return | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment