client server

This commit is contained in:
joshuafc
2021-03-05 20:54:31 +08:00
parent 462e3c4b55
commit b21427c8a4
5 changed files with 302 additions and 35 deletions

View File

@@ -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 {

View File

@@ -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)
}
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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())