mirror of
https://github.com/joshuafc/ntVPN.git
synced 2025-12-24 13:28:13 +08:00
client server
This commit is contained in:
@@ -3,6 +3,8 @@ package network
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
@@ -63,14 +65,19 @@ func (v *VPNCommandMsg) ToDetailMsg(msg interface{}) error {
|
||||
return decoder.Decode(msg)
|
||||
}
|
||||
|
||||
func ReadCommand(conn *net.Conn) (msg *VPNCommandMsg, err error) {
|
||||
func ReadCommand(conn net.Conn) (msg *VPNCommandMsg, err error) {
|
||||
msg = new(VPNCommandMsg)
|
||||
err = gob.NewDecoder(*conn).Decode(msg)
|
||||
err = gob.NewDecoder(conn).Decode(msg)
|
||||
log.Println("Read Data From " + conn.RemoteAddr().String() + ":")
|
||||
log.Println(fmt.Sprintf("%+v", msg))
|
||||
return
|
||||
}
|
||||
|
||||
func WriteCommand(conn *net.Conn, msg *VPNCommandMsg) (err error) {
|
||||
err = gob.NewEncoder(*conn).Encode(msg)
|
||||
func WriteCommand(conn net.Conn, msg *VPNCommandMsg) (err error) {
|
||||
err = gob.NewEncoder(conn).Encode(msg)
|
||||
log.Println("Write Data To" +
|
||||
" " + conn.RemoteAddr().String() + ":")
|
||||
log.Println(fmt.Sprintf("%+v", msg))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -95,11 +102,17 @@ type ClientUnRegisterResponseMsg struct {
|
||||
}
|
||||
|
||||
type ClientQueryOthersRequestMsg struct {
|
||||
Ok bool
|
||||
}
|
||||
|
||||
type ClientInfo struct {
|
||||
Ip string
|
||||
Mac string
|
||||
Mask string
|
||||
Addr net.Addr
|
||||
}
|
||||
|
||||
type ClientQueryOthersResponseMsg struct {
|
||||
Ok bool
|
||||
Clients []ClientInfo
|
||||
}
|
||||
|
||||
type ClientConnectToRequestMsg struct {
|
||||
|
||||
@@ -2,46 +2,121 @@ package main
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/gob"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/joshuafc/ntVPN/network"
|
||||
"github.com/xtaci/kcp-go"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gob.Register(&net.UDPAddr{})
|
||||
|
||||
serverAddress := flag.String("server", "127.0.0.1", "specify ntVPN server IP address")
|
||||
serverPort := flag.Int("port", 3455, "specify ntVPN server port")
|
||||
encryptKey := flag.String("encry_key", "password", "specify ntVPN transfer encrypt password")
|
||||
|
||||
vpnIP := flag.String("vpn_ip", "192.168.101.2", "specify vpn node ip address")
|
||||
vpnMask := flag.String("vpn_mask", "255.255.255.0", "specify vpn node mask")
|
||||
vpnMac := flag.String("vpn_mac", "", "specify vpn node mac address")
|
||||
|
||||
readChan := make(chan *network.VPNCommandMsg, 5)
|
||||
writeChan := make(chan *network.VPNCommandMsg, 5)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if len(*vpnMac) == 0 {
|
||||
buf := make([]byte, 6)
|
||||
_, err := rand.Read(buf)
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
return
|
||||
}
|
||||
// Set the local bit
|
||||
buf[0] |= 2
|
||||
*vpnMac = fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5])
|
||||
}
|
||||
|
||||
key := pbkdf2.Key([]byte(*encryptKey), []byte(*encryptKey), 1024, 32, sha1.New)
|
||||
block, _ := kcp.NewAESBlockCrypt(key)
|
||||
|
||||
if sess, err := kcp.DialWithOptions(*serverAddress+":"+strconv.Itoa(*serverPort), block, 10, 3); err == nil {
|
||||
var conn net.Conn
|
||||
conn = sess
|
||||
defer conn.Close()
|
||||
|
||||
var msg network.ClientRegisterRequestMsg
|
||||
msg.Ip = "192.168.100.4"
|
||||
network.WriteCommand(&conn, network.FromDetailMsg(network.ClientRegisterRequest, &msg))
|
||||
handleServer(conn)
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
msg, err := network.ReadCommand(conn)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
readChan <- msg
|
||||
}
|
||||
}()
|
||||
|
||||
func handleServer(s net.Conn) {
|
||||
for {
|
||||
cmd, err := network.ReadCommand(&s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
switch {
|
||||
case cmd.CommandType == network.ClientRegisterRequest:
|
||||
var detailMsg network.ClientRegisterRequestMsg
|
||||
err = cmd.ToDetailMsg(detailMsg)
|
||||
fmt.Println("%+v", detailMsg)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case cmd, ok := <-writeChan:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err := network.WriteCommand(conn, cmd)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
timer1 := time.NewTimer(0)
|
||||
defer timer1.Stop()
|
||||
go func() {
|
||||
for range timer1.C {
|
||||
var msg network.ClientRegisterRequestMsg
|
||||
msg.Ip = *vpnIP
|
||||
msg.Mac = *vpnMac
|
||||
msg.Mask = *vpnMask
|
||||
writeChan <- network.FromDetailMsg(network.ClientRegisterRequest, msg)
|
||||
timer1.Reset(time.Second * 30)
|
||||
}
|
||||
}()
|
||||
|
||||
timer2 := time.NewTimer(time.Second * 2)
|
||||
defer timer2.Stop()
|
||||
for {
|
||||
select {
|
||||
case cmd, ok := <-readChan:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
switch {
|
||||
case cmd.CommandType == network.ClientRegisterResponse:
|
||||
var detailMsg network.ClientRegisterResponseMsg
|
||||
err = cmd.ToDetailMsg(&detailMsg)
|
||||
if !detailMsg.Ok {
|
||||
log.Print("Register Failed!")
|
||||
}
|
||||
log.Println(fmt.Sprintf("%+v", detailMsg))
|
||||
case cmd.CommandType == network.ClientQueryOthersResponse:
|
||||
var detailMsg network.ClientQueryOthersResponseMsg
|
||||
err = cmd.ToDetailMsg(&detailMsg)
|
||||
log.Println(fmt.Sprintf("%+v", detailMsg))
|
||||
default:
|
||||
log.Print("Data Not Process.")
|
||||
}
|
||||
case <-timer2.C:
|
||||
timer2.Reset(time.Second * 2)
|
||||
var msg network.ClientQueryOthersRequestMsg
|
||||
writeChan <- network.FromDetailMsg(network.ClientQueryOthersRequest, &msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/joshuafc/ntVPN/network"
|
||||
"github.com/xtaci/kcp-go"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gob.Register(&net.UDPAddr{})
|
||||
serverContext, serverQuit := context.WithCancel(context.Background())
|
||||
defer serverQuit()
|
||||
var clientManager ClientManager
|
||||
clientManager.ConnMap = make(map[net.Addr]*ClientItem)
|
||||
clientManager.IpMap = make(map[string]*ClientItem)
|
||||
clientManager.MacMap = make(map[string]*ClientItem)
|
||||
clientManager.mutex = new(sync.Mutex)
|
||||
serverPort := flag.Int("port", 3455, "specify ntVPN server port")
|
||||
encryptKey := flag.String("encry_key", "password", "specify ntVPN transfer encrypt password")
|
||||
flag.Parse()
|
||||
@@ -25,24 +36,191 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
go handleClient(s)
|
||||
go clientManager.handleConnection(serverContext, s)
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleClient(s net.Conn) {
|
||||
for {
|
||||
cmd, err := network.ReadCommand(&s)
|
||||
if err != nil {
|
||||
return
|
||||
type ClientItem struct {
|
||||
conn net.Conn
|
||||
writeLock *sync.Mutex
|
||||
clientContext context.Context
|
||||
clientContextCancelFunc func()
|
||||
clientInfo network.ClientRegisterRequestMsg
|
||||
readChan chan *network.VPNCommandMsg
|
||||
writeChan chan *network.VPNCommandMsg
|
||||
}
|
||||
|
||||
func (clientItem *ClientItem) ProcessMsg(msg *network.VPNCommandMsg) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClientManager struct {
|
||||
ConnMap map[net.Addr]*ClientItem
|
||||
IpMap map[string]*ClientItem
|
||||
MacMap map[string]*ClientItem
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) P2PRequest(toClientItem *ClientItem) error {
|
||||
clientManager.mutex.Lock()
|
||||
defer clientManager.mutex.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) P2PResponse(toClientItem *ClientItem) error {
|
||||
clientManager.mutex.Lock()
|
||||
defer clientManager.mutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) AddClient(clientItem *ClientItem) error {
|
||||
clientManager.mutex.Lock()
|
||||
defer clientManager.mutex.Unlock()
|
||||
clientManager.ConnMap[clientItem.conn.RemoteAddr()] = clientItem
|
||||
return nil
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) UpdateClient(clientItem *ClientItem) error {
|
||||
clientManager.mutex.Lock()
|
||||
defer clientManager.mutex.Unlock()
|
||||
|
||||
ip_val, ip_ok := clientManager.IpMap[clientItem.clientInfo.Ip]
|
||||
mac_val, mac_ok := clientManager.MacMap[clientItem.clientInfo.Mac]
|
||||
|
||||
if ip_ok && ip_val.conn.RemoteAddr() != clientItem.conn.RemoteAddr() {
|
||||
return errors.New("Error: Ip addr Used!")
|
||||
}
|
||||
|
||||
if mac_ok && mac_val.conn.RemoteAddr() != clientItem.conn.RemoteAddr() {
|
||||
return errors.New("Error: Mac addr Used!")
|
||||
}
|
||||
|
||||
clientManager.IpMap[clientItem.clientInfo.Ip] = clientItem
|
||||
clientManager.MacMap[clientItem.clientInfo.Mac] = clientItem
|
||||
return nil
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) DeleteClient(clientItem *ClientItem) error {
|
||||
clientManager.mutex.Lock()
|
||||
defer clientManager.mutex.Unlock()
|
||||
if clientItem.clientInfo.Ip != "" {
|
||||
delete(clientManager.IpMap, clientItem.clientInfo.Ip)
|
||||
}
|
||||
if clientItem.clientInfo.Mac != "" {
|
||||
delete(clientManager.MacMap, clientItem.clientInfo.Mac)
|
||||
}
|
||||
delete(clientManager.ConnMap, clientItem.conn.RemoteAddr())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) GetClients(selfAddr net.Addr) (clientInfo []network.ClientInfo) {
|
||||
clientInfo = make([]network.ClientInfo, 0)
|
||||
clientManager.mutex.Lock()
|
||||
defer clientManager.mutex.Unlock()
|
||||
for k, v := range clientManager.ConnMap {
|
||||
if k == selfAddr {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case cmd.CommandType == network.ClientRegisterRequest:
|
||||
var detailMsg network.ClientRegisterRequestMsg
|
||||
err = cmd.ToDetailMsg(&detailMsg)
|
||||
fmt.Println("%+v", detailMsg)
|
||||
clientInfo = append(clientInfo, network.ClientInfo{
|
||||
Ip: v.clientInfo.Ip,
|
||||
Mac: v.clientInfo.Mac,
|
||||
Mask: v.clientInfo.Mask,
|
||||
Addr: k,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (clientManager *ClientManager) handleConnection(serverContext context.Context, s net.Conn) {
|
||||
var clientItem ClientItem
|
||||
clientItem.writeLock = new(sync.Mutex)
|
||||
clientItem.clientContext, clientItem.clientContextCancelFunc = context.WithCancel(serverContext)
|
||||
clientItem.conn = s
|
||||
|
||||
clientManager.AddClient(&clientItem)
|
||||
|
||||
clientItem.readChan = make(chan *network.VPNCommandMsg, 5)
|
||||
clientItem.writeChan = make(chan *network.VPNCommandMsg, 5)
|
||||
|
||||
defer func() {
|
||||
clientItem.clientContextCancelFunc()
|
||||
clientManager.DeleteClient(&clientItem)
|
||||
close(clientItem.writeChan)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
msg, err := network.ReadCommand(s)
|
||||
if err != nil && clientItem.clientContext.Err() != nil {
|
||||
close(clientItem.readChan)
|
||||
break
|
||||
}
|
||||
clientItem.readChan <- msg
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case cmd, ok := <-clientItem.writeChan:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err := network.WriteCommand(s, cmd)
|
||||
if err != nil {
|
||||
s.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
Exit:
|
||||
for {
|
||||
select {
|
||||
case cmd, ok := <-clientItem.readChan:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
switch true {
|
||||
case cmd.CommandType == network.ClientRegisterRequest:
|
||||
err := cmd.ToDetailMsg(&clientItem.clientInfo)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err1 := clientManager.UpdateClient(&clientItem)
|
||||
var response network.ClientRegisterResponseMsg
|
||||
response.Ok = err1 == nil
|
||||
clientItem.writeChan <- network.FromDetailMsg(network.ClientRegisterResponse, &response)
|
||||
if !response.Ok {
|
||||
break Exit
|
||||
}
|
||||
case cmd.CommandType == network.ClientUnRegisterRequest:
|
||||
err := cmd.ToDetailMsg(&clientItem.clientInfo)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
clientManager.DeleteClient(&clientItem)
|
||||
var response network.ClientUnRegisterResponseMsg
|
||||
response.Ok = true
|
||||
clientItem.writeChan <- network.FromDetailMsg(network.ClientUnRegisterResponse, &response)
|
||||
|
||||
case cmd.CommandType == network.ClientQueryOthersRequest:
|
||||
var response network.ClientQueryOthersResponseMsg
|
||||
response.Clients = clientManager.GetClients(s.RemoteAddr())
|
||||
clientItem.writeChan <- network.FromDetailMsg(network.ClientQueryOthersResponse, &response)
|
||||
default:
|
||||
err := clientItem.ProcessMsg(cmd)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
case <-clientItem.clientContext.Done():
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ func lookup_adapter_reg_path(deviceRegistry string) string {
|
||||
}
|
||||
|
||||
func CreateTapDevice(deviceName string) (TapDevice, error) {
|
||||
deviceName = "" // ignore deviceName on Windows
|
||||
key, ok := r.OpenKey(r.LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, r.READ)
|
||||
if ok != nil {
|
||||
println(ok.Error())
|
||||
|
||||
Reference in New Issue
Block a user