Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
FlowerWrong committed Apr 21, 2018
1 parent 44e31f4 commit 3988415
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 3 deletions.
199 changes: 199 additions & 0 deletions cmd/netstack/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package main

import (
"fmt"
"log"
"math/rand"
"net"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"time"

"github.com/FlowerWrong/netstack/tcpip"
"github.com/FlowerWrong/netstack/tcpip/link/fdbased"
"github.com/FlowerWrong/netstack/tcpip/network/ipv4"
"github.com/FlowerWrong/netstack/tcpip/network/ipv6"
"github.com/FlowerWrong/netstack/tcpip/stack"
"github.com/FlowerWrong/netstack/tcpip/transport/tcp"
"github.com/FlowerWrong/netstack/waiter"
"github.com/FlowerWrong/water"
)

// sudo go run cmd/netstack/main.go tun2 10.0.0.2 8090
// telnet 10.0.0.2 8090

func echo(wq *waiter.Queue, ep tcpip.Endpoint) {
defer ep.Close()

// Create wait queue entry that notifies a channel.
waitEntry, notifyCh := waiter.NewChannelEntry(nil)

wq.EventRegister(&waitEntry, waiter.EventIn)
defer wq.EventUnregister(&waitEntry)

for {
v, err := ep.Read(nil)
if err != nil {
if err == tcpip.ErrWouldBlock {
<-notifyCh
continue
}

return
}

ep.Write(tcpip.SlicePayload(v), tcpip.WriteOptions{})
}
}

func execCommand(name, sargs string) error {
args := strings.Split(sargs, " ")
cmd := exec.Command(name, args...)
log.Println("exec command: %s %s", name, sargs)
return cmd.Run()
}

func addRoute(tun string, subnet *net.IPNet) error {
ip := subnet.IP
maskIP := net.IP(subnet.Mask)
sargs := fmt.Sprintf("-n add -net %s -netmask %s -interface %s", ip.String(), maskIP.String(), tun)
return execCommand("route", sargs)
}

func main() {
if len(os.Args) != 4 {
log.Fatal("Usage: ", os.Args[0], " <tun-device> <local-address> <local-port>")
}

// tunName := os.Args[1]
addrName := os.Args[2]
portName := os.Args[3]

rand.Seed(time.Now().UnixNano())

log.SetFlags(log.LstdFlags | log.Lshortfile)

// Parse the IP address. Support both ipv4 and ipv6.
parsedAddr := net.ParseIP(addrName)
if parsedAddr == nil {
log.Fatalf("Bad IP address: %v", addrName)
}

var addr tcpip.Address
var proto tcpip.NetworkProtocolNumber
if parsedAddr.To4() != nil {
addr = tcpip.Address(parsedAddr.To4())
proto = ipv4.ProtocolNumber
} else if parsedAddr.To16() != nil {
addr = tcpip.Address(parsedAddr.To16())
proto = ipv6.ProtocolNumber
} else {
log.Fatalf("Unknown IP type: %v", addrName)
}

localPort, err := strconv.Atoi(portName)
if err != nil {
log.Fatalf("Unable to convert port %v: %v", portName, err)
}

// Create the stack with ip and tcp protocols, then add a tun-based
// NIC and address.
s := stack.New([]string{ipv4.ProtocolName, ipv6.ProtocolName}, []string{tcp.ProtocolName})

var mtu uint32 = 1500

ifce, err := water.New(water.Config{
DeviceType: water.TUN,
})
if err != nil {
log.Fatal("Create tun interface failed", err)
}
log.Println("[tun] interface name is", ifce.Name())

if runtime.GOOS == "darwin" {
sargs := fmt.Sprintf("%s 10.0.0.1 10.0.0.2 mtu %d netmask 255.255.255.0 up", ifce.Name(), mtu)
if err := execCommand("/sbin/ifconfig", sargs); err != nil {
log.Println(err)
return
}
} else if runtime.GOOS == "linux" {
sargs := fmt.Sprintf("%s 10.0.0.1 netmask 255.255.255.0", ifce.Name())
if err := execCommand("/sbin/ifconfig", sargs); err != nil {
log.Println(err)
return
}
} else {
log.Println("not support os")
return
}

// Parse the mac address.
maddr, err := net.ParseMAC("aa:00:01:01:01:01")
if err != nil {
log.Fatalf("Bad MAC address: aa:00:01:01:01:01")
}

linkID := fdbased.New(ifce, &fdbased.Options{
FD: ifce.Fd(),
MTU: 1500,
EthernetHeader: false,
Address: tcpip.LinkAddress(maddr),
})

if err := s.CreateNIC(1, linkID, true, addr, uint16(localPort)); err != nil {
log.Fatal(err)
}

if err := s.AddAddress(1, proto, addr); err != nil {
log.Fatal(err)
}

// Add default route.
s.SetRouteTable([]tcpip.Route{
{
Destination: tcpip.Address(strings.Repeat("\x00", len(addr))),
Mask: tcpip.Address(strings.Repeat("\x00", len(addr))),
Gateway: "",
NIC: 1,
},
})

// Create TCP endpoint, bind it, then start listening.
var wq waiter.Queue
ep, e := s.NewEndpoint(tcp.ProtocolNumber, proto, &wq)
if err != nil {
log.Fatal(e)
}

defer ep.Close()

if err := ep.Bind(tcpip.FullAddress{0, "", uint16(localPort)}, nil); err != nil {
log.Fatal("Bind failed: ", err)
}

if err := ep.Listen(1024); err != nil {
log.Fatal("Listen failed: ", err)
}

// Wait for connections to appear.
waitEntry, notifyCh := waiter.NewChannelEntry(nil)
wq.EventRegister(&waitEntry, waiter.EventIn)
defer wq.EventUnregister(&waitEntry)

for {
n, wq, err := ep.Accept()
if err != nil {
if err == tcpip.ErrWouldBlock {
<-notifyCh
continue
}

log.Fatal("Accept() failed:", err)
}

go echo(wq, n)
}
}
5 changes: 4 additions & 1 deletion dns/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ func (d *DNS) resolve(r *dns.Msg) (*dns.Msg, error) {

r, _, err := d.client.Exchange(r, ns)
if err != nil {
// eg: write: network is down
// eg: i/o timeout
log.Printf("[dns] resolve %s on %s failed: %v", qname, ns, err)
return
}

if r.Rcode == dns.RcodeServerFailure {
// eg: code 2
log.Printf("[dns] resolve %s on %s failed: code %d", qname, ns, r.Rcode)
return
}
Expand Down Expand Up @@ -122,6 +125,7 @@ func (d *DNS) doIPv4Query(r *dns.Msg) (*dns.Msg, error) {
// resolve
msg, err := d.resolve(r)
if err != nil || len(msg.Answer) == 0 {
// dns failed
return msg, err
}

Expand Down Expand Up @@ -159,7 +163,6 @@ func (d *DNS) doIPv4Query(r *dns.Msg) (*dns.Msg, error) {
// set domain as a non-proxy-domain
d.DNSTablePtr.SetNonProxyDomain(domain, msg.Answer[0].Header().Ttl)

// final
return msg, err
}

Expand Down
13 changes: 12 additions & 1 deletion tun2socks/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,18 @@ func NewNetstack(app *App) tcpip.NetworkProtocolNumber {
log.Fatal("New random port failed")
}

linkID := fdbased.New(app.Ifce, app.Cfg.General.Mtu, nil)
// Parse the mac address.
maddr, err := net.ParseMAC("aa:00:01:01:01:01")
if err != nil {
log.Fatalf("Bad MAC address: aa:00:01:01:01:01")
}

linkID := fdbased.New(app.Ifce, &fdbased.Options{
FD: app.Ifce.Fd(),
MTU: app.Cfg.General.Mtu,
EthernetHeader: false,
Address: tcpip.LinkAddress(maddr),
})
if err := app.S.CreateNIC(NICId, linkID, true, addr, app.HookPort); err != nil {
log.Fatal("Create NIC failed", err)
}
Expand Down
2 changes: 1 addition & 1 deletion tun2socks/tcp2socks.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ readFromRemote:
}
var m uintptr
var err *tcpip.Error
m, err = tcpTunnel.localEndpoint.Write(chunk, nil)
m, err = tcpTunnel.localEndpoint.Write(tcpip.SlicePayload(chunk), tcpip.WriteOptions{})
n := int(m)
if err != nil {
if err == tcpip.ErrWouldBlock {
Expand Down

0 comments on commit 3988415

Please sign in to comment.