mirror of https://github.com/n1nj4sec/pupy.git
164 lines
3.0 KiB
Go
164 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
|
|
"github.com/LiamHaworth/go-tproxy"
|
|
)
|
|
|
|
var (
|
|
EchoBindHost = "0.0.0.0"
|
|
EchoBindPort = 31337
|
|
EchoMagic = "\xDE\xAD\xBE\xEF"
|
|
)
|
|
|
|
func isHttpEchoRequest(body []byte) bool {
|
|
buf := bufio.NewReader(bytes.NewReader(body))
|
|
req, err := http.ReadRequest(buf)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
for k, v := range req.URL.Query() {
|
|
if strings.ToLower(k) == "echo" {
|
|
for _, value := range v {
|
|
if value == EchoMagic {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func handleConn(conn net.Conn) {
|
|
defer conn.Close()
|
|
|
|
buffer := make([]byte, 32768)
|
|
|
|
n, err := conn.Read(buffer)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
switch {
|
|
case isHttpEchoRequest(buffer):
|
|
log.Println(
|
|
"TCP/HTTP: "+conn.RemoteAddr().String(), "->",
|
|
conn.LocalAddr().String(), " b: ", n,
|
|
)
|
|
conn.Write(
|
|
[]byte(fmt.Sprintf(
|
|
"HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream"+
|
|
"\r\nContent-Length: %d\r\n\r\n", n,
|
|
)),
|
|
)
|
|
case bytes.Equal(buffer[:4], []byte(EchoMagic)):
|
|
log.Println(
|
|
"TCP/RAW: "+conn.RemoteAddr().String(), "->",
|
|
conn.LocalAddr().String(), " b: ", n,
|
|
)
|
|
default:
|
|
return
|
|
}
|
|
|
|
conn.Write(buffer[:n])
|
|
}
|
|
|
|
func tcpEchoServer(listener net.Listener) {
|
|
for {
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
|
log.Printf("Temporary error while accepting connection: %s", netErr)
|
|
}
|
|
|
|
log.Fatalf("Unrecoverable error while accepting connection: %s", err)
|
|
return
|
|
}
|
|
|
|
go handleConn(conn)
|
|
}
|
|
}
|
|
|
|
func udpEchoServer(listener *net.UDPConn) {
|
|
buffer := make([]byte, 1500)
|
|
|
|
for {
|
|
n, srcAddr, dstAddr, err := tproxy.ReadFromUDP(listener, buffer)
|
|
if err != nil {
|
|
log.Fatalln("UDP reader failed: ", err)
|
|
}
|
|
|
|
if srcAddr.IP.Equal(dstAddr.IP) || n < 4 {
|
|
continue
|
|
}
|
|
|
|
if !bytes.Equal(buffer[:4], []byte(EchoMagic)) {
|
|
continue
|
|
}
|
|
|
|
log.Println(
|
|
"UDP: "+srcAddr.String(), "->",
|
|
dstAddr.String(), " b: ", n,
|
|
)
|
|
|
|
remoteConn, err := tproxy.DialUDP("udp", dstAddr, srcAddr)
|
|
if err != nil {
|
|
log.Println(err)
|
|
continue
|
|
}
|
|
|
|
_, err = remoteConn.Write(buffer[:n])
|
|
if err != nil {
|
|
log.Println(err)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
log.Print("Echo server starting")
|
|
|
|
log.Printf("Binding TCP TProxy listener to %s:%d", EchoBindHost, EchoBindPort)
|
|
tcpListener, err := tproxy.ListenTCP(
|
|
"tcp", &net.TCPAddr{
|
|
IP: net.ParseIP(EchoBindHost),
|
|
Port: EchoBindPort,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Fatalf("Encountered error while binding listener: %s", err)
|
|
return
|
|
}
|
|
|
|
udpListener, err := tproxy.ListenUDP(
|
|
"udp", &net.UDPAddr{
|
|
IP: net.ParseIP(EchoBindHost),
|
|
Port: EchoBindPort,
|
|
})
|
|
|
|
if err != nil {
|
|
log.Fatalf("Encountered error while binding listener: %s", err)
|
|
return
|
|
}
|
|
|
|
go tcpEchoServer(tcpListener)
|
|
go udpEchoServer(udpListener)
|
|
|
|
interruptListener := make(chan os.Signal)
|
|
signal.Notify(interruptListener, os.Interrupt)
|
|
<-interruptListener
|
|
|
|
log.Println("Interrupted")
|
|
}
|