add
This commit is contained in:
parent
467d96803f
commit
6b88744d14
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
57
cmd/main.go
Normal file
57
cmd/main.go
Normal file
@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"pingtunnel"
|
||||
)
|
||||
|
||||
var usage = `
|
||||
Usage:
|
||||
|
||||
pingtunnel -t server -l SERVER_IP:4455 -t TARGET_IP:443
|
||||
|
||||
pingtunnel -t client -l LOCAL_IP:4455 -t SERVER_IP:4455
|
||||
|
||||
`
|
||||
|
||||
func main() {
|
||||
fmt.Println("start...")
|
||||
|
||||
t := flag.String("type", "client", "client or server")
|
||||
listen := flag.String("l", ":4455", "listen addr")
|
||||
target := flag.String("t", ":443", "target addr")
|
||||
flag.Usage = func() {
|
||||
fmt.Printf(usage)
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() != 0 {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("type %s\n", *t)
|
||||
fmt.Printf("listen %s\n", *listen)
|
||||
fmt.Printf("target %s\n", *target)
|
||||
|
||||
if *t == "server" {
|
||||
s, err := pingtunnel.NewPingTunnelServer(*listen, *target)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Printf("Server Listen %s (%s) Target %s (%s):\n", s.Addr(), s.IPAddr(), s.TargetAddr(), s.TargetIPAddr())
|
||||
s.Run()
|
||||
}
|
||||
if *t == "client" {
|
||||
c, err := pingtunnel.NewPingTunnelClient(*listen, *target)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Printf("Client Listen %s (%s) Target %s (%s):\n", c.Addr(), c.IPAddr(), c.TargetAddr(), c.TargetIPAddr())
|
||||
c.Run()
|
||||
}
|
||||
}
|
232
src/pingtunnel/pingtunnel.go
Normal file
232
src/pingtunnel/pingtunnel.go
Normal file
@ -0,0 +1,232 @@
|
||||
package pingtunnel
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewPingTunnelServer(addr string, target string) (*PingTunnelServer, error) {
|
||||
|
||||
ipaddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ipaddrTarget, err := net.ResolveTCPAddr("tcp", target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PingTunnelServer{
|
||||
ipaddr: ipaddr,
|
||||
addr: addr,
|
||||
ipaddrTarget: ipaddrTarget,
|
||||
addrTarget: target,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewPingTunnelClient(addr string, target string) (*PingTunnelClient, error) {
|
||||
|
||||
ipaddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ipaddrTarget, err := net.ResolveTCPAddr("tcp", target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PingTunnelClient{
|
||||
ipaddr: ipaddr,
|
||||
addr: addr,
|
||||
ipaddrTarget: ipaddrTarget,
|
||||
addrTarget: target,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type PingTunnelClient struct {
|
||||
ipaddr *net.TCPAddr
|
||||
addr string
|
||||
|
||||
ipaddrTarget *net.TCPAddr
|
||||
addrTarget string
|
||||
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
type PingTunnelServer struct {
|
||||
ipaddr *net.TCPAddr
|
||||
addr string
|
||||
|
||||
ipaddrTarget *net.TCPAddr
|
||||
addrTarget string
|
||||
|
||||
conn net.PacketConn
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) Addr() string {
|
||||
return p.addr
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) IPAddr() *net.TCPAddr {
|
||||
return p.ipaddr
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) TargetAddr() string {
|
||||
return p.addrTarget
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) TargetIPAddr() *net.TCPAddr {
|
||||
return p.ipaddrTarget
|
||||
}
|
||||
|
||||
func (p *PingTunnelClient) Addr() string {
|
||||
return p.addr
|
||||
}
|
||||
|
||||
func (p *PingTunnelClient) IPAddr() *net.TCPAddr {
|
||||
return p.ipaddr
|
||||
}
|
||||
|
||||
func (p *PingTunnelClient) TargetAddr() string {
|
||||
return p.addrTarget
|
||||
}
|
||||
|
||||
func (p *PingTunnelClient) TargetIPAddr() *net.TCPAddr {
|
||||
return p.ipaddrTarget
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) Run() {
|
||||
conn, err := net.ListenPacket("udp4", p.addr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
p.conn = conn
|
||||
|
||||
p.Recv()
|
||||
}
|
||||
|
||||
func (p *PingTunnelClient) Run() {
|
||||
|
||||
conn, err := net.Dial("udp4", p.addrTarget)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
p.conn = conn
|
||||
|
||||
n := 0
|
||||
for {
|
||||
p.Send(n, []byte("haha"))
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PingTunnelClient) Send(id int, data []byte) error {
|
||||
|
||||
body := &Msg{
|
||||
ID: id,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
msg := &icmp.Message{
|
||||
Type: ipv4.ICMPTypeExtendedEchoRequest,
|
||||
Code: 0,
|
||||
Body: body,
|
||||
}
|
||||
|
||||
bytes, err := msg.Marshal(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
if _, err := p.conn.Write(bytes); err != nil {
|
||||
if neterr, ok := err.(*net.OpError); ok {
|
||||
if neterr.Err == syscall.ENOBUFS {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Printf("send %d\n", id)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) Recv() error {
|
||||
|
||||
for {
|
||||
bytes := make([]byte, 512)
|
||||
p.conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100))
|
||||
n, srcaddr, err := p.conn.ReadFrom(bytes)
|
||||
if err != nil {
|
||||
if neterr, ok := err.(*net.OpError); ok {
|
||||
if neterr.Timeout() {
|
||||
// Read timeout
|
||||
continue
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sbytes []byte
|
||||
sbytes = ipv4Payload(bytes)
|
||||
|
||||
var m *icmp.Message
|
||||
if m, err = icmp.ParseMessage(1, sbytes[:n]); err != nil {
|
||||
return fmt.Errorf("Error parsing icmp message")
|
||||
}
|
||||
|
||||
fmt.Printf("%d %d %d %s \n", m.Type, m.Code, n, srcaddr)
|
||||
}
|
||||
}
|
||||
|
||||
func ipv4Payload(b []byte) []byte {
|
||||
if len(b) < ipv4.HeaderLen {
|
||||
return b
|
||||
}
|
||||
hdrlen := int(b[0]&0x0f) << 2
|
||||
return b[hdrlen:]
|
||||
}
|
||||
|
||||
type Msg struct {
|
||||
ID int // identifier
|
||||
Data []byte // data
|
||||
}
|
||||
|
||||
func (p *Msg) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4 + len(p.Data)
|
||||
}
|
||||
|
||||
func (p *Msg) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4+len(p.Data))
|
||||
binary.BigEndian.PutUint32(b, uint32(p.ID))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (p *PingTunnelServer) listen(netProto string, source string) *icmp.PacketConn {
|
||||
|
||||
conn, err := icmp.ListenPacket(netProto, source)
|
||||
if err != nil {
|
||||
fmt.Printf("Error listening for ICMP packets: %s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
return conn
|
||||
}
|
Loading…
Reference in New Issue
Block a user