transparent-proxy/main.go

99 lines
2.4 KiB
Go

package main
import (
"flag"
"fmt"
"git.eve.moe/jackyyf/transparent-proxy/server"
"io"
"net"
)
var port = flag.Int("port", 1080, "Listen port of the server")
func main() {
flag.Parse()
go IPv4Handler()
go IPv6Handler()
select {}
}
func IPv4Handler() {
proxy_listener, err := server.NewIPv4TransparentListener(fmt.Sprintf("0.0.0.0:%d", *port))
if err != nil {
panic(err)
}
for {
conn, err := proxy_listener.Accept()
if err != nil {
fmt.Println("Accept Error: ", err.Error())
continue
}
// fmt.Printf("Accepted connection: %s => %s\n", conn.TCPConn().RemoteAddr().String(), conn.RealAddr().String())
go handle4(conn)
}
}
func IPv6Handler() {
proxy_listener, err := server.NewIPv6TransparentListener(fmt.Sprintf("[::]:%d", *port))
if err != nil {
panic(err)
}
for {
conn, err := proxy_listener.Accept()
if err != nil {
fmt.Println("Accept Error: ", err.Error())
continue
}
// fmt.Printf("Accepted connection: %s => %s\n", conn.TCPConn().RemoteAddr().String(), conn.RealAddr().String())
go handle6(conn)
}
}
func pipeThenClose(reader io.Reader, writer io.WriteCloser) {
defer writer.Close()
buff := make([]byte, 4096)
for {
n, err := reader.Read(buff)
if n > 0 {
_, err := writer.Write(buff[:n])
if err != nil {
fmt.Printf("Write Error: %#v\n", err.Error())
return
}
}
if err == io.EOF {
// fmt.Println("Reader reached EOF, closing.")
return
}
if err != nil {
// Enable this line ONLY FOR DEBUG PURPOSE.
// fmt.Printf("Read Error: %#v\n", err.Error())
return
}
}
}
func handle4(conn server.TransparentConnection) {
rconn, err := net.DialTCP("tcp4", nil, conn.RealAddr())
if err != nil {
fmt.Println("Connect to ", conn.RealAddr().String(), " error: ", err.Error())
conn.TCPConn().Close()
return
}
// fmt.Printf("ESTABLISHED %s <=> %s\n", conn.TCPConn().RemoteAddr().String(), conn.RealAddr().String())
go pipeThenClose(conn.TCPConn(), rconn)
go pipeThenClose(rconn, conn.TCPConn())
}
func handle6(conn server.TransparentConnection) {
rconn, err := net.DialTCP("tcp6", conn.TCPConn().RemoteAddr().(*net.TCPAddr), conn.RealAddr())
if err != nil {
fmt.Println("Connect to ", conn.RealAddr().String(), " error: ", err.Error())
conn.TCPConn().Close()
return
}
// fmt.Printf("ESTABLISHED %s <=> %s\n", conn.TCPConn().RemoteAddr().String(), conn.RealAddr().String())
go pipeThenClose(conn.TCPConn(), rconn)
go pipeThenClose(rconn, conn.TCPConn())
}