diff --git a/.gitignore b/.gitignore index 6d70cde..b2b8c45 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,8 @@ erebrus-linux-x64 # bin folder -/bin \ No newline at end of file +/bin + +env.text +D:/jjsahdd/server.json +D:/jjsahdd/wg0.conf diff --git a/.sample-env b/.sample-env new file mode 100644 index 0000000..d75158b --- /dev/null +++ b/.sample-env @@ -0,0 +1,45 @@ +#Application Parameters +LOAD_CONFIG_FILE=false +RUNTYPE=debug +SERVER=0.0.0.0 +HTTP_PORT=9080 +GRPC_PORT=9090 +REGION=EU + +# PASETO Specifications +PASETO_EXPIRATION_IN_HOURS=168 +AUTH_EULA=I Accept the Erebrus Terms of Service https://erebrus.io/terms.html for accessing the application. +SIGNED_BY=Erebrus +FOOTER=Erebrus 2024 + +#Node Specifications +HOST_IP=ip_addr +DOMAIN=http://ip_addr:9080/ +NODE_NAME= +MNEMONIC= +CHAIN_NAME= +NODE_TYPE= +NODE_CONFIG= + +#Gateway Specifications +GATEWAY_WALLET=0x0 +GATEWAY_DOMAIN=https://dev.gateway.erebrus.io/ +GATEWAY_PEERID=/ip4/35.239.34.5/tcp/9001/p2p/12D3KooWH6NjtNwQ3QRELdjqTce38marCzXkA7hHxnuVmJwc8oJA + +#Wireguard Specifications +WG_CONF_DIR= +WG_CLIENTS_DIR= +WG_INTERFACE_NAME=wg0.conf +WG_ENDPOINT_HOST=ip_addr +WG_ENDPOINT_PORT=51820 +WG_IPv4_SUBNET=10.0.0.1/24 +WG_IPv6_SUBNET=fd9f:0000::10:0:0:1/64 +WG_DNS=1.1.1.1 +WG_ALLOWED_IP_1=0.0.0.0/0 +WG_ALLOWED_IP_2=::/0 +WG_PRE_UP=echo WireGuard PreUp +WG_POST_UP=iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +WG_PRE_DOWN=echo WireGuard PreDown +WG_POST_DOWN=iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + + diff --git "a/D:\\jjsahdd/server.json" "b/D:\\jjsahdd/server.json" deleted file mode 100644 index babd6a5..0000000 --- "a/D:\\jjsahdd/server.json" +++ /dev/null @@ -1,23 +0,0 @@ -{ - "Address": [ - "10.0.0.1/24" - ], - "ListenPort": 51820, - "PrivateKey": "6O38xfKg6Jo4x4nm9KMwK/NYZNYjNIi+Lx28VqZAzlw=", - "PublicKey": "u3b+DCYWlT+4u8LHw0w0P1Jd3NOPMAvwDpZzO17HfnE=", - "Endpoint": "ip_addr", - "PersistentKeepalive": 16, - "DNS": [ - "1.1.1.1" - ], - "AllowedIPs": [ - "0.0.0.0/0", - "::/0" - ], - "PreUp": "echo WireGuard PreUp", - "PostUp": "iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE", - "PreDown": "echo WireGuard PreDown", - "PostDown": "iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE", - "CreatedAt": 464703000, - "UpdatedAt": 464703000 -} \ No newline at end of file diff --git "a/D:\\jjsahdd/wg0.conf" "b/D:\\jjsahdd/wg0.conf" deleted file mode 100644 index f3c40ee..0000000 --- "a/D:\\jjsahdd/wg0.conf" +++ /dev/null @@ -1,10 +0,0 @@ -# Updated: 464703000 / Created: 464703000 -[Interface] -Address = 10.0.0.1/24 -ListenPort = 51820 -PrivateKey = 6O38xfKg6Jo4x4nm9KMwK/NYZNYjNIi+Lx28VqZAzlw= - -PreUp = echo WireGuard PreUp -PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -PreDown = echo WireGuard PreDown -PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2ad49a4..e2e7355 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ FROM golang:alpine AS build-app RUN apk update && apk add --no-cache git WORKDIR /app COPY . . -RUN go build -o erebrus . +RUN go build -ldflags "-X main.version=1.0.0 -X main.codeHash=$(git rev-parse HEAD)" -o erebrus . FROM alpine:latest WORKDIR /app @@ -13,12 +13,13 @@ COPY --from=build-app /app/webapp ./webapp COPY wg-watcher.sh . RUN chmod +x ./erebrus ./wg-watcher.sh RUN apk update && apk add --no-cache bash openresolv bind-tools wireguard-tools gettext inotify-tools iptables -ENV LOAD_CONFIG_FILE=$LOAD_CONFIG_FILE RUNTYPE=$RUNTYPE SERVER=$SERVER HTTP_PORT=$HTTP_PORT GRPC_PORT=$GRPC_PORT MASTERNODE_URL=$MASTERNODE_URL -ENV REGION=$REGION DOMAIN=$DOMAIN REGION_NAME=$REGION_NAME REGION_CODE=$REGION_CODE +ENV LOAD_CONFIG_FILE=$LOAD_CONFIG_FILE RUNTYPE=$RUNTYPE SERVER=$SERVER HTTP_PORT=$HTTP_PORT GRPC_PORT=$GRPC_PORT GATEWAY_DOMAIN=$GATEWAY_DOMAIN +ENV NODE_NAME=$NODE_NAME REGION=$REGION DOMAIN=$DOMAIN REGION_NAME=$REGION_NAME REGION_CODE=$REGION_CODE ENV WG_CONF_DIR=$WG_CONF_DIR WG_CLIENTS_DIR=$WG_CLIENTS_DIR WG_KEYS_DIR=$WG_KEYS_DIR WG_INTERFACE_NAME=$WG_INTERFACE_NAME ENV WG_ENDPOINT_HOST=$WG_ENDPOINT_HOST WG_ENDPOINT_PORT=$WG_ENDPOINT_PORT WG_IPv4_SUBNET=$WG_IPv4_SUBNET WG_IPv6_SUBNET=$WG_IPv6_SUBNET ENV WG_DNS=$WG_DNS WG_ALLOWED_IP_1=$WG_ALLOWED_IP_1 WG_ALLOWED_IP_2=$WG_ALLOWED_IP_2 ENV WG_PRE_UP=$WG_PRE_UP WG_POST_UP=$WG_POST_UP WG_PRE_DOWN=$WG_PRE_DOWN WG_POST_DOWN=$WG_POST_DOWN +ENV NODE_CONFIG=$NODE_CONFIG NODE_TYPE=$NODE_TYPE RUN echo $'#!/usr/bin/env bash\n\ set -eo pipefail\n\ /app/erebrus &\n\ diff --git a/api/v1/authenticate/authenticate.go b/api/v1/authenticate/authenticate.go index b6beaf4..993eda6 100644 --- a/api/v1/authenticate/authenticate.go +++ b/api/v1/authenticate/authenticate.go @@ -1,13 +1,13 @@ package authenticate import ( + "fmt" "net/http" "os" "github.com/NetSepio/erebrus/api/v1/authenticate/challengeid" "github.com/NetSepio/erebrus/util/pkg/auth" "github.com/NetSepio/erebrus/util/pkg/claims" - "github.com/NetSepio/erebrus/util/pkg/cryptosign" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -38,22 +38,100 @@ func authenticate(c *gin.Context) { } userAuthEULA := os.Getenv("AUTH_EULA") message := userAuthEULA + req.ChallengeId - walletAddress, isCorrect, err := cryptosign.CheckSign(req.Signature, req.ChallengeId, message) - if err == cryptosign.ErrFlowIdNotFound { - log.WithFields(log.Fields{ - "err": err, - }).Error("FlowId Not Found") - errResponse := ErrAuthenticate(err.Error()) - c.JSON(http.StatusNotFound, errResponse) - return - } + var ( + isCorrect bool + walletAddress string + ) - if err != nil { + switch req.ChainName { + case "ethereum", "peaq": + userAuthEULA := userAuthEULA + message := userAuthEULA + req.ChallengeId + walletAddress, isCorrect, err = CheckSignEthereum(req.Signature, req.ChallengeId, message) + + if err == ErrChallengeIdNotFound { + + log.WithFields(log.Fields{"err": err}).Errorf("Challenge Id not found") + + c.JSON(http.StatusNotFound, ErrAuthenticate("Challenge Id not found")) + + return + } + + if err != nil { + fmt.Println("error", err) + + log.WithFields(log.Fields{"err": err}).Errorf("failed to CheckSignature, error %v", err.Error()) + + c.JSON(http.StatusNotFound, ErrAuthenticate("failed to CheckSignature, error :"+err.Error())) + return + } + + case "aptos": + userAuthEULA := userAuthEULA + message := fmt.Sprintf("APTOS\nmessage: %v\nnonce: %v", userAuthEULA, req.ChallengeId) + walletAddress, isCorrect, err = CheckSignAptos(req.Signature, req.ChallengeId, message, req.PubKey) + + if err == ErrChallengeIdNotFound { + log.WithFields(log.Fields{"err": err}).Errorf("Challenge Id not found") + + c.JSON(http.StatusNotFound, ErrAuthenticate("Challenge Id not found")) + + return + } + + if err != nil { + + log.WithFields(log.Fields{"err": err}).Errorf("failed to CheckSignature, error %v", err.Error()) + + c.JSON(http.StatusNotFound, ErrAuthenticate("failed to CheckSignature, error :"+err.Error())) + return + } + + case "sui": + walletAddress, isCorrect, err = CheckSignSui(req.Signature, req.ChallengeId) + + if err == ErrChallengeIdNotFound { + + log.WithFields(log.Fields{"err": err}).Errorf("Challenge Id not found") + + c.JSON(http.StatusNotFound, ErrAuthenticate("Challenge Id not found")) + return + } + + if err != nil { + log.WithFields(log.Fields{"err": err}).Errorf("failed to CheckSignature, error %v", err.Error()) + + c.JSON(http.StatusNotFound, ErrAuthenticate("failed to CheckSignature, error : "+err.Error())) + return + } + + case "solana": + walletAddress, isCorrect, err = CheckSignSolana(req.Signature, req.ChallengeId, message, req.PubKey) + + if err == ErrChallengeIdNotFound { + log.WithFields(log.Fields{"err": err}).Errorf("Challenge Id not found") + c.JSON(http.StatusNotFound, ErrAuthenticate("Challenge Id not found")) + return + } + + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Errorf("failed to CheckSignature, error : %v", err.Error()) + errResponse := ErrAuthenticate("failed to CheckSignature, error :" + err.Error()) + c.JSON(http.StatusInternalServerError, errResponse) + return + + } + + default: + info := "chain name must be between solana, peaq, aptos, sui, eclipse, ethereum" log.WithFields(log.Fields{ "err": err, - }).Error("failed to CheckSignature") - errResponse := ErrAuthenticate(err.Error()) + }).Errorf("Invalid chain name, INFO : %s\n", info) + errResponse := ErrAuthenticate("failed to CheckSignature, error :" + "Invalid chain name, INFO : " + info) c.JSON(http.StatusInternalServerError, errResponse) return } diff --git a/api/v1/authenticate/challengeid/challengeid.go b/api/v1/authenticate/challengeid/challengeid.go new file mode 100644 index 0000000..29be963 --- /dev/null +++ b/api/v1/authenticate/challengeid/challengeid.go @@ -0,0 +1,192 @@ +package challengeid + +import ( + "encoding/hex" + "math/big" + "net/http" + "os" + "regexp" + "strings" + "time" + + "github.com/NetSepio/erebrus/core" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +type FlowId struct { + WalletAddress string + FlowId string `gorm:"primary_key"` +} +type MemoryDB struct { + WalletAddress string + ChainName string + Timestamp time.Time +} + +var Data map[string]MemoryDB + +// Get walletAddress, chain and return eula, challengeId +func GetChallengeId(c *gin.Context) { + walletAddress := c.Query("walletAddress") + chainName := c.Query("chainName") + + if walletAddress == "" { + log.WithFields(log.Fields{ + "err": "empty Wallet Address", + }).Error("failed to create client") + + response := core.MakeErrorResponse(403, "Empty Wallet Address", nil, nil, nil) + c.JSON(http.StatusForbidden, response) + return + } + + if chainName == "" { + log.WithFields(log.Fields{ + "err": "empty Chain name", + }).Error("failed to create client") + + response := core.MakeErrorResponse(403, "Empty Wallet Address", nil, nil, nil) + c.JSON(http.StatusForbidden, response) + return + } + + if err := ValidateAddress(chainName, walletAddress); err != nil { + + info := "chain name = " + chainName + "; please pass chain name between solana, peaq, aptos, sui, eclipse, ethereum" + + switch err { + case ErrInvalidChain: + log.WithFields(log.Fields{"err": ErrInvalidChain}).Error("failed to create client") + response := core.MakeErrorResponse(http.StatusNotAcceptable, ErrInvalidChain.Error()+info, nil, nil, nil) + c.JSON(http.StatusNotAcceptable, response) + return + case ErrInvalidAddress: + log.WithFields(log.Fields{"err": ErrInvalidAddress}).Error("failed to create client") + response := core.MakeErrorResponse(http.StatusNotAcceptable, ErrInvalidAddress.Error(), nil, nil, nil) + c.JSON(http.StatusNotAcceptable, response) + return + } + return + } + + challengeId, err := GenerateChallengeId(walletAddress, chainName) + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Error("failed to create FlowId") + response := core.MakeErrorResponse(500, err.Error(), nil, nil, nil) + c.JSON(http.StatusInternalServerError, response) + return + } + userAuthEULA := os.Getenv("AUTH_EULA") + payload := GetChallengeIdPayload{ + ChallengeId: challengeId, + Eula: userAuthEULA, + } + c.JSON(200, payload) +} + +func GenerateChallengeId(walletAddress string, chainName string) (string, error) { + challengeId := uuid.NewString() + var dbdata MemoryDB + dbdata.WalletAddress = walletAddress + dbdata.Timestamp = time.Now() + dbdata.ChainName = chainName + Data = map[string]MemoryDB{ + challengeId: dbdata, + } + return challengeId, nil +} + +// ValidateAddress validates a wallet address for the specified blockchain +func ValidateAddress(chain, address string) error { + // Convert chain name to lowercase for case-insensitive comparison + + switch chain { + case "ethereum": + if !ValidateAddressEtherium(address) { + return ErrInvalidAddress + } + case "solana", "eclipse": + if !ValidateSolanaAddress(address) { + return ErrInvalidAddress + } + + case "peaq": + if !ValidatePeaqAddress(address) { + return ErrInvalidAddress + } + + case "aptos": + if !ValidateAptosAddress(address) { + return ErrInvalidAddress + } + + case "sui": + if !ValidateSuiAddress(address) { + return ErrInvalidAddress + } + + default: + return ErrInvalidChain + } + + return nil +} + +// ValidateSolanaAddress checks if the given string is a valid Solana wallet address +func ValidateSolanaAddress(address string) bool { + if len(address) < 32 || len(address) > 44 { + return false + } + + // Solana addresses only contain base58 characters + matched, _ := regexp.MatchString("^[1-9A-HJ-NP-Za-km-z]+$", address) + return matched +} + +// ValidatePeaqAddress checks if the given string is a valid Peaq wallet address +func ValidatePeaqAddress(address string) bool { + if len(address) != 48 || !strings.HasPrefix(address, "5") { + return false + } + + // Peaq addresses only contain base58 characters + matched, _ := regexp.MatchString("^[1-9A-HJ-NP-Za-km-z]+$", address) + return matched +} + +// ValidateAptosAddress checks if the given string is a valid Aptos wallet address +func ValidateAptosAddress(address string) bool { + if len(address) != 66 || !strings.HasPrefix(address, "0x") { + return false + } + + // Remove "0x" prefix and check if remaining string is valid hex + address = strings.TrimPrefix(address, "0x") + _, err := hex.DecodeString(address) + return err == nil +} + +// ValidateSuiAddress checks if the given string is a valid Sui wallet address +func ValidateSuiAddress(address string) bool { + if len(address) != 42 || !strings.HasPrefix(address, "0x") { + return false + } + + // Remove "0x" prefix and check if remaining string is valid hex + address = strings.TrimPrefix(address, "0x") + _, err := hex.DecodeString(address) + return err == nil +} + +func ValidateAddressEtherium(address string) bool { + if len(address) != 42 || !strings.HasPrefix(address, "0x") { + return false + } + _, isValid := big.NewInt(0).SetString(address[2:], 16) + return isValid +} diff --git a/api/v1/authenticate/challengeid/challengid.go b/api/v1/authenticate/challengeid/challengid.go deleted file mode 100644 index affc134..0000000 --- a/api/v1/authenticate/challengeid/challengid.go +++ /dev/null @@ -1,98 +0,0 @@ -package challengeid - -import ( - "net/http" - "os" - "time" - - "github.com/NetSepio/erebrus/core" - "github.com/NetSepio/erebrus/util" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gin-gonic/gin" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" -) - -// type User struct { -// Name string `json:"name,omitempty"` -// WalletAddress string `gorm:"primary_key" json:"walletAddress"` -// FlowIds []FlowId `gorm:"foreignkey:WalletAddress" json:"-"` -// } -type FlowId struct { - WalletAddress string - FlowId string `gorm:"primary_key"` -} -type Db struct { - WalletAddress string - Timestamp time.Time -} - -var Data map[string]Db - -// ApplyRoutes applies router to gin Router -// func ApplyRoutes(r *gin.RouterGroup) { -// g := r.Group("/flowid") -// { -// g.GET("", GetFlowId) -// } -// } - -func GetChallengeId(c *gin.Context) { - walletAddress := c.Query("walletAddress") - - if walletAddress == "" { - log.WithFields(log.Fields{ - "err": "empty Wallet Address", - }).Error("failed to create client") - - response := core.MakeErrorResponse(403, "Empty Wallet Address", nil, nil, nil) - c.JSON(http.StatusForbidden, response) - return - } - _, err := hexutil.Decode(walletAddress) - if err != nil { - log.WithFields(log.Fields{ - "err": err, - }).Error("Wallet address (walletAddress) is not valid") - - response := core.MakeErrorResponse(400, err.Error(), nil, nil, nil) - c.JSON(http.StatusBadRequest, response) - return - } - if !util.RegexpWalletEth.MatchString(walletAddress) { - log.WithFields(log.Fields{ - "err": err, - }).Error("Wallet address (walletAddress) is not valid") - response := core.MakeErrorResponse(400, err.Error(), nil, nil, nil) - c.JSON(http.StatusBadRequest, response) - return - } - challengeId, err := GenerateChallengeId(walletAddress) - if err != nil { - log.WithFields(log.Fields{ - "err": err, - }).Error("failed to create FlowId") - response := core.MakeErrorResponse(500, err.Error(), nil, nil, nil) - c.JSON(http.StatusInternalServerError, response) - return - } - userAuthEULA := os.Getenv("AUTH_EULA") - payload := GetChallengeIdPayload{ - ChallengeId: challengeId, - Eula: userAuthEULA, - } - c.JSON(200, payload) -} - -func GenerateChallengeId(walletAddress string) (string, error) { - - challengeId := uuid.NewString() - var dbdata Db - dbdata.WalletAddress = walletAddress - dbdata.Timestamp = time.Now() - Data = map[string]Db{ - challengeId: dbdata, - } - return challengeId, nil -} diff --git a/api/v1/authenticate/challengeid/types.go b/api/v1/authenticate/challengeid/types.go index 60bf8b6..a323dce 100644 --- a/api/v1/authenticate/challengeid/types.go +++ b/api/v1/authenticate/challengeid/types.go @@ -1,6 +1,13 @@ package challengeid +import "errors" + type GetChallengeIdPayload struct { Eula string `json:"eula,omitempty"` ChallengeId string `json:"challangeId"` } + +var ( + ErrInvalidChain = errors.New("unsupported blockchain") + ErrInvalidAddress = errors.New("invalid address format") +) diff --git a/api/v1/authenticate/types.go b/api/v1/authenticate/types.go index d5274be..6bcaec5 100644 --- a/api/v1/authenticate/types.go +++ b/api/v1/authenticate/types.go @@ -3,6 +3,8 @@ package authenticate type AuthenticateRequest struct { ChallengeId string `json:"challengeId" binding:"required"` Signature string `json:"signature" binding:"required"` + PubKey string `json:"pubKey" binding:"omitempty"` + ChainName string `json:"chainName" binding:"required"` } type AuthenticatePayload struct { diff --git a/api/v1/authenticate/validate.chain.authentication.go b/api/v1/authenticate/validate.chain.authentication.go new file mode 100644 index 0000000..3a54d78 --- /dev/null +++ b/api/v1/authenticate/validate.chain.authentication.go @@ -0,0 +1,168 @@ +package authenticate + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/NetSepio/erebrus/api/v1/authenticate/challengeid" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/minio/blake2b-simd" + "github.com/mr-tron/base58" + "golang.org/x/crypto/nacl/sign" + "golang.org/x/crypto/sha3" +) + +var ErrChallengeIdNotFound = errors.New("challenge id not found") + +func CheckSignAptos(signature string, challangeId string, message string, pubKey string) (string, bool, error) { + signatureInBytes, err := hexutil.Decode(signature) + if err != nil { + return "", false, err + } + + sha3_i := sha3.New256() + signatureInBytes = append(signatureInBytes, []byte(message)...) + pubBytes, err := hexutil.Decode(pubKey) + if err != nil { + return "", false, err + } + sha3_i.Write(pubBytes) + sha3_i.Write([]byte{0}) + hash := sha3_i.Sum(nil) + addr := hexutil.Encode(hash) + + dbData, exists := challengeid.Data[challangeId] + if !exists { + return "", false, ErrChallengeIdNotFound + } + + if !strings.EqualFold(addr, dbData.WalletAddress) { + return "", false, err + } + + msgGot, matches := sign.Open(nil, signatureInBytes, (*[32]byte)(pubBytes)) + if !matches || string(msgGot) != message { + return "", false, err + } + return dbData.WalletAddress, true, nil + +} + +func CheckSignEthereum(signature string, flowId string, message string) (string, bool, error) { + + newMsg := fmt.Sprintf("\x19Ethereum Signed Message:\n%v%v", len(message), message) + + // fmt.Println("newMsg : ", newMsg) + + newMsgHash := crypto.Keccak256Hash([]byte(newMsg)) + signatureInBytes, err := hexutil.Decode(signature) + if err != nil { + return "", false, err + } + // check if the signature is in the [R || S || V] format + if len(signatureInBytes) != 65 { + return "", false, errors.New("invalid signature length") + } + if signatureInBytes[64] == 27 || signatureInBytes[64] == 28 { + signatureInBytes[64] -= 27 + } + pubKey, err := crypto.SigToPub(newMsgHash.Bytes(), signatureInBytes) + + if err != nil { + return "", false, err + } + + //Get address from public key + walletAddress := crypto.PubkeyToAddress(*pubKey) + + flowIdData := challengeid.Data[flowId] + if (challengeid.MemoryDB{}) == flowIdData { + return "", false, ErrChallengeIdNotFound + } + if strings.EqualFold(flowIdData.WalletAddress, walletAddress.String()) { + return flowIdData.WalletAddress, true, nil + } else { + return "", false, errors.New("mismatch wallet_address") + } +} + +func CheckSignSui(signature string, challangeId string) (string, bool, error) { + // Decode signature + signatureBytes, err := base64.StdEncoding.DecodeString(signature) + if err != nil { + return "", false, err + } + + // Assuming ED25519 signature format + size := 32 + + publicKey := signatureBytes[len(signatureBytes)-size:] + pubKey := &ecdsa.PublicKey{ + Curve: elliptic.P256(), // Curve is not used in serialization + X: new(big.Int).SetBytes(publicKey[:]), // Set X coordinate + Y: new(big.Int).SetBytes(publicKey[32:]), // Set Y coordinate + } + if pubKey.X == nil || pubKey.Y == nil { + return "", false, err + } + // Serialize the public key into bytes + pubKeyBytes := pubKey.X.Bytes() + + // Pad X coordinate bytes to ensure they are the same length as the curve's bit size + paddingLen := (pubKey.Curve.Params().BitSize + 7) / 8 + pubKeyBytes = append(make([]byte, paddingLen-len(pubKeyBytes)), pubKeyBytes...) + + // Concatenate the signature scheme flag (0x00 for Ed25519) with the serialized public key bytes + concatenatedBytes := append([]byte{0x00}, pubKeyBytes...) + + // Compute the BLAKE2b hash + hash := blake2b.Sum256(concatenatedBytes) + + // The resulting hash is the Sui address + suiAddress := "0x" + hex.EncodeToString(hash[:]) + + dbData, exists := challengeid.Data[challangeId] + if !exists { + return "", false, ErrChallengeIdNotFound + } + + if !strings.EqualFold(suiAddress, dbData.WalletAddress) { + return "", false, err + } + + return dbData.WalletAddress, true, nil +} + +func CheckSignSolana(signature string, challangeId string, message string, pubKey string) (string, bool, error) { + + bytes, err := base58.Decode(pubKey) + if err != nil { + return "", false, err + } + messageAsBytes := []byte(message) + + signedMessageAsBytes, err := hex.DecodeString(signature) + + if err != nil { + + return "", false, err + } + + dbData, exists := challengeid.Data[challangeId] + if !exists { + return "", false, ErrChallengeIdNotFound + } + + ed25519.Verify(bytes, messageAsBytes, signedMessageAsBytes) + + return dbData.WalletAddress, true, nil + +} diff --git a/api/v1/middleware/middleware.go b/api/v1/middleware/middleware.go index 0ab7e8b..6842871 100644 --- a/api/v1/middleware/middleware.go +++ b/api/v1/middleware/middleware.go @@ -1,19 +1,20 @@ package middleware import ( - log "github.com/sirupsen/logrus" "os" + + log "github.com/sirupsen/logrus" ) -func CheckMasterNodeAccess(decryptedWalletAddress any) bool { - AllowedWalletAddress := os.Getenv("MASTERNODE_WALLET") +func CheckGatewayAccess(decryptedWalletAddress any) bool { + AllowedWalletAddress := os.Getenv("GATEWAY_WALLET") if AllowedWalletAddress == "*" { return true } if decryptedWalletAddress != AllowedWalletAddress { log.WithFields(log.Fields{ - "err": "Updates Not Allowed for the Following Wallet Address", - }).Error("Updates Not Allowed for the Following Wallet Address") + "err": "Updates Not Allowed for the Given Wallet Address", + }).Error("Updates Not Allowed for the Given Wallet Address") return false } return true diff --git a/blockchain/solana/soon/setdata.go b/blockchain/solana/soon/setdata.go deleted file mode 100644 index 815f370..0000000 --- a/blockchain/solana/soon/setdata.go +++ /dev/null @@ -1,243 +0,0 @@ -// package main - -// import ( -// "bytes" -// "fmt" -// "os" -// "os/exec" -// ) - -// func main() { -// // Path to the JavaScript file -// jsFilePath := "setdata.js" -// projectDir := "." - -// // Your private key in base58 format (replace with your actual private key) -// privateKey := "kRVZ7yFvAZFufaUJheFecbp8gESdEFB6hzwRXzzdJGZdnH6hTvdhhZf65bCfG2fAyb9AxFuw3JTvXDPUPXwA5rG" - -// // Step 1: Check if `@solana/web3.js` is installed -// fmt.Println("Checking if @solana/web3.js is installed...") -// checkPackage := exec.Command("npm", "list", "@solana/web3.js") -// checkPackage.Dir = projectDir -// if err := checkPackage.Run(); err != nil { -// fmt.Println("@solana/web3.js is not installed. Installing now...") -// installPackage := exec.Command("npm", "install", "@solana/web3.js") -// installPackage.Dir = projectDir -// if err := installPackage.Run(); err != nil { -// fmt.Printf("Error installing @solana/web3.js: %s\n", err.Error()) -// return -// } -// fmt.Println("Successfully installed @solana/web3.js.") -// } else { -// fmt.Println("@solana/web3.js is already installed.") -// } - -// // Step 2: Run npm install -// fmt.Println("Running npm install to ensure all dependencies are installed...") -// npmInstall := exec.Command("npm", "install") -// npmInstall.Dir = projectDir -// if err := npmInstall.Run(); err != nil { -// fmt.Printf("Error running npm install: %s\n", err.Error()) -// return -// } -// fmt.Println("All dependencies are installed.") - -// // Step 3: Execute the JavaScript file -// fmt.Println("Executing JavaScript file:", jsFilePath) -// cmd := exec.Command("node", jsFilePath) -// cmd.Dir = projectDir - -// // Set the private key as an environment variable -// cmd.Env = append(os.Environ(), fmt.Sprintf("SOLANA_PRIVATE_KEY=%s", privateKey)) - -// // Buffers to capture the output and errors -// var stdout, stderr bytes.Buffer -// cmd.Stdout = &stdout -// cmd.Stderr = &stderr - -// // Run the command -// err := cmd.Run() - -// // Handle errors and output -// if err != nil { -// fmt.Printf("Error executing JavaScript: %s\n", err.Error()) -// fmt.Printf("Stderr: %s\n", stderr.String()) -// return -// } - -// fmt.Println("JavaScript Output:") -// fmt.Println(stdout.String()) -// } -package soon_solana - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "os/exec" - "text/template" -) - -// func main() { -// SoonNodeCreation() -// } - -type NodeDetails struct { - PrivateKey string `json:"private_key"` // Private key in base58 format - PeaqDid string `json:"peaq_did"` // DID (Decentralized Identifier) - NodeName string `json:"nodename"` // Name of the node - IPAddress string `json:"ipaddress"` // IP address of the node - ISPInfo string `json:"ispinfo"` // Information about the ISP - Region string `json:"region"` // Region of the node - Location string `json:"location"` // Geographical location of the node -} - -func SoonNodeCreation(data NodeDetails) { - // Path to the JavaScript file - // jsFilePath := "setdata.js" - jsFilePath := "blockchain/solana/soon/setdata.js" - - // - projectDir := "blockchain/solana/soon/." - - // Set environment variable to pass to JS file - os.Setenv("SOLANA_PRIVATE_KEY", data.PrivateKey) - - // Node details to pass to JavaScript file (dynamic values) - peaqDid := data.PeaqDid - nodename := data.NodeName - ipaddress := data.IPAddress - ispinfo := data.IPAddress - region := data.Region - location := data.Location - - // Step 1: Check if `@solana/web3.js` is installed - fmt.Println("Checking if @solana/web3.js is installed...") - checkPackage := exec.Command("npm", "list", "@solana/web3.js") - checkPackage.Dir = projectDir - if err := checkPackage.Run(); err != nil { - fmt.Println("@solana/web3.js is not installed. Installing now...") - installPackage := exec.Command("npm", "install", "@solana/web3.js") - installPackage.Dir = projectDir - if err := installPackage.Run(); err != nil { - fmt.Printf("Error installing @solana/web3.js: %s\n", err.Error()) - return - } - fmt.Println("Successfully installed @solana/web3.js.") - } else { - fmt.Println("@solana/web3.js is already installed.") - } - - // Step 2: Check if `@project-serum/anchor` is installed - fmt.Println("Checking if @project-serum/anchor is installed...") - checkAnchorPackage := exec.Command("npm", "list", "@project-serum/anchor") - checkAnchorPackage.Dir = projectDir - if err := checkAnchorPackage.Run(); err != nil { - fmt.Println("@project-serum/anchor is not installed. Installing now...") - installAnchorPackage := exec.Command("npm", "install", "@project-serum/anchor") - installAnchorPackage.Dir = projectDir - if err := installAnchorPackage.Run(); err != nil { - fmt.Printf("Error installing @project-serum/anchor: %s\n", err.Error()) - return - } - fmt.Println("Successfully installed @project-serum/anchor.") - } else { - fmt.Println("@project-serum/anchor is already installed.") - } - - // Step 2: Run npm install - fmt.Println("Running npm install to ensure all dependencies are installed...") - npmInstall := exec.Command("npm", "install") - npmInstall.Dir = projectDir - if err := npmInstall.Run(); err != nil { - fmt.Printf("Error running npm install: %s\n", err.Error()) - return - } - fmt.Println("All dependencies are installed.") - - // Step 3: Inject dynamic data into setdata.js - err := injectDataIntoJS(jsFilePath, peaqDid, nodename, ipaddress, ispinfo, region, location) - if err != nil { - fmt.Printf("Error injecting data into JS file: %s\n", err.Error()) - return - } - - // Step 4: Execute the modified JavaScript file - fmt.Println("Executing data file:", jsFilePath) - cmd := exec.Command("node", jsFilePath) - cmd.Dir = projectDir - - // Buffers to capture the output and errors - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - - // Run the command - err = cmd.Run() - - // Handle errors and output - if err != nil { - fmt.Printf("Error executing JavaScript: %s\n", err.Error()) - fmt.Printf("Stderr: %s\n", stderr.String()) - return - } - - fmt.Println("Data Output:") - fmt.Println(stdout.String()) -} - -// Function to inject dynamic data into the JS file -func injectDataIntoJS(jsFilePath, peaqDid, nodename, ipaddress, ispinfo, region, location string) error { - // Read the template JS file - jsTemplate, err := ioutil.ReadFile(jsFilePath) - if err != nil { - return fmt.Errorf("failed to read JS file: %w", err) - } - - // Define a template to inject the dynamic values - jsTemplateStr := string(jsTemplate) - tmpl, err := template.New("js").Parse(jsTemplateStr) - if err != nil { - return fmt.Errorf("failed to parse template: %w", err) - } - - // Create a struct to hold dynamic data - data := struct { - PeaqDid string - NodeName string - IPAddr string - ISPInfo string - Region string - Location string - }{ - PeaqDid: peaqDid, - NodeName: nodename, - IPAddr: ipaddress, - ISPInfo: ispinfo, - Region: region, - Location: location, - } - - // Create a temporary JS file with dynamic data injected - tempJsFilePath := jsFilePath + ".temp" - tempFile, err := os.Create(tempJsFilePath) - if err != nil { - return fmt.Errorf("failed to create temporary JS file: %w", err) - } - defer tempFile.Close() - - // Execute the template with dynamic data and write to the temp file - err = tmpl.Execute(tempFile, data) - if err != nil { - return fmt.Errorf("failed to execute template: %w", err) - } - - // Replace the original JS file with the modified one - err = os.Rename(tempJsFilePath, jsFilePath) - if err != nil { - return fmt.Errorf("failed to rename temp JS file: %w", err) - } - - return nil -} diff --git a/blockchain/solana/soon/setdata.js b/blockchain/solana/soon/setdata.js deleted file mode 100644 index 33b801c..0000000 --- a/blockchain/solana/soon/setdata.js +++ /dev/null @@ -1,295 +0,0 @@ -// The following variables will be dynamically injected by the Go code - -const peaqDid = "did:peaq:testnode123"; // Placeholder for dynamic Peaq DID -const nodename = "TestVPNNode"; // Placeholder for dynamic Node Name -const ipaddress = "192.168.1.100"; // Placeholder for dynamic IP Address -const ispinfo = "TestISP"; // Placeholder for dynamic ISP Information -const region = "EU-Central"; // Placeholder for dynamic Region -const location = "Frankfurt, Germany"; // Placeholder for dynamic Location - -// Log the values to check if they're injected correctly -console.log("Peaq DID:", peaqDid); -console.log("Node Name:", nodename); -console.log("IP Address:", ipaddress); -console.log("ISP Info:", ispinfo); -console.log("Region:", region); -console.log("Location:", location); - -const { - Connection, - PublicKey, - Keypair, - SystemProgram, - LAMPORTS_PER_SOL, -} = require("@solana/web3.js"); -const { Program, AnchorProvider, BN } = require("@project-serum/anchor"); -const fs = require("fs"); -const path = require("path"); -const bs58 = require("bs58"); // Import the base58 decoding library - -// Program ID from your deployment -const PROGRAM_ID = new PublicKey( - "3ypCkXQWiAFkNk7bo8bnZFxUVmVEWCqpBoY7v4vgPnHJ" -); - -// Fixed IDL with correct string type definitions -const IDL = { - version: "0.1.0", - name: "erebrus", - instructions: [ - { - name: "registerVpnNode", - accounts: [ - { - name: "vpnNode", - isMut: true, - isSigner: false, - }, - { - name: "user", - isMut: true, - isSigner: true, - }, - { - name: "systemProgram", - isMut: false, - isSigner: false, - }, - ], - args: [ - { - name: "userNodeNum", - type: "u64", - }, - { - name: "peaqDid", - type: "string", - }, - { - name: "nodename", - type: "string", - }, - { - name: "ipaddress", - type: "string", - }, - { - name: "ispinfo", - type: "string", - }, - { - name: "region", - type: "string", - }, - { - name: "location", - type: "string", - }, - ], - discriminator: [254, 249, 109, 84, 232, 26, 70, 251], - }, - ], - accounts: [ - { - name: "VpnNode", - type: { - kind: "struct", - fields: [ - { - name: "nodeId", - type: "u64", - }, - { - name: "user", - type: "publicKey", - }, - { - name: "peaqDid", - type: "string", - }, - { - name: "nodename", - type: "string", - }, - { - name: "ipaddress", - type: "string", - }, - { - name: "ispinfo", - type: "string", - }, - { - name: "region", - type: "string", - }, - { - name: "location", - type: "string", - }, - { - name: "status", - type: "u8", - }, - { - name: "canClose", - type: "bool", - }, - ], - }, - discriminator: [154, 255, 245, 194, 44, 120, 114, 244], - }, - ], -}; - -async function checkBalance(connection, publicKey) { - try { - const balance = await connection.getBalance(publicKey); - return balance / LAMPORTS_PER_SOL; - } catch (error) { - console.error("Error checking balance:", error); - return 0; - } -} - -async function registerVpnNode() { - try { - // Connect to devnet - const connection = new Connection( - "https://rpc.devnet.soo.network/rpc", - "confirmed" - ); - - // Load private key from environment variable (base58 string) - const privateKeyEnv = process.env.SOLANA_PRIVATE_KEY; - if (!privateKeyEnv) { - console.error("Error: SOLANA_PRIVATE_KEY environment variable is not set."); - process.exit(1); - } - - // Decode the private key from base58 format to Uint8Array - const privateKey = bs58.decode(privateKeyEnv); - const wallet = Keypair.fromSecretKey(privateKey); - - console.log("Using wallet address:", wallet.publicKey.toString()); - - // Check balance - const balance = await checkBalance(connection, wallet.publicKey); - console.log("Current balance:", balance, "SOL"); - - // Setup provider - const provider = new AnchorProvider( - connection, - { - publicKey: wallet.publicKey, - signTransaction: async (tx) => { - tx.partialSign(wallet); - return tx; - }, - signAllTransactions: async (txs) => { - return txs.map((t) => { - t.partialSign(wallet); - return t; - }); - }, - }, - { commitment: "confirmed" } - ); - - // Create program interface - const program = new Program(IDL, PROGRAM_ID, provider); - - // Generate a node number - // const userNodeNum = new BN(1); - let userNodeNum = new BN(Date.now()); // Timestamp in milliseconds - - // Print the userNodeNum - console.log("Generated userNodeNum (on-chain counter):", userNodeNum.toString()); - - - // Find PDA - const [vpnNodePDA] = PublicKey.findProgramAddressSync( - [Buffer.from("vpn"), userNodeNum.toArrayLike(Buffer, "le", 8)], - program.programId - ); - - console.log("VPN Node PDA:", vpnNodePDA.toString()); - - // Register VPN node - const nodeDetails = { - userNodeNum: userNodeNum, - peaqDid: "did:peaq:testnode123", - nodename: "TestVPNNode", - ipaddress: "192.168.1.100", - ispinfo: "TestISP", - region: "EU-Central", - location: "Frankfurt, Germany", - }; - - const tx = await program.methods - .registerVpnNode( - nodeDetails.userNodeNum, - nodeDetails.peaqDid, - nodeDetails.nodename, - nodeDetails.ipaddress, - nodeDetails.ispinfo, - nodeDetails.region, - nodeDetails.location - ) - .accounts({ - vpnNode: vpnNodePDA, - user: wallet.publicKey, - systemProgram: SystemProgram.programId, - }) - .signers([wallet]) - .rpc(); - - console.log("Transaction signature:", tx); - - // Fetch and display the created account - await connection.confirmTransaction(tx); - const vpnNodeAccount = await program.account.vpnNode.fetch(vpnNodePDA); - - console.log("Created VPN Node Account:", { - nodeId: vpnNodeAccount.nodeId.toString(), - user: vpnNodeAccount.user.toString(), - peaqDid: vpnNodeAccount.peaqDid, - nodename: vpnNodeAccount.nodename, - ipaddress: vpnNodeAccount.ipaddress, - ispinfo: vpnNodeAccount.ispinfo, - region: vpnNodeAccount.region, - location: vpnNodeAccount.location, - status: vpnNodeAccount.status, - canClose: vpnNodeAccount.canClose, - }); - - return { - success: true, - signature: tx, - vpnNodePDA: vpnNodePDA.toString(), - account: vpnNodeAccount, - }; - } catch (error) { - console.error("Error registering VPN node:", error); - if (error.logs) { - console.error("Program logs:", error.logs); - } - return { - success: false, - error: error.message, - logs: error.logs, - }; - } -} - -// Execute the registration -console.log("Starting VPN node registration..."); -registerVpnNode() - .then((result) => { - console.log("Registration result:", result); - process.exit(result.success ? 0 : 1); - }) - .catch((error) => { - console.error("Fatal error:", error); - process.exit(1); - }); \ No newline at end of file diff --git a/core/chainName.go b/core/chainName.go deleted file mode 100644 index f3ea7e0..0000000 --- a/core/chainName.go +++ /dev/null @@ -1,25 +0,0 @@ -package core - -import ( - "fmt" - "log" - "os" -) - -var ChainName string - -// Function to load the chain name from the environment and save it to the global variable -func LoadChainName() { - // Load environment variables from the .env file - // err := godotenv.Load() - // if err != nil { - // log.Fatalf("Error loading .env file") - // } - - // Get the CHAIN_NAME variable from the environment - ChainName = os.Getenv("CHAIN_NAME") - if ChainName == "" { - log.Fatalf("CHAIN_NAME environment variable is not set") - } - fmt.Printf("Chain Name: %s\n", ChainName) -} diff --git a/core/client.go b/core/client.go index 606e188..e446513 100644 --- a/core/client.go +++ b/core/client.go @@ -4,7 +4,6 @@ import ( "crypto/rand" "errors" "fmt" - "io/ioutil" "math/big" "os" "path/filepath" @@ -159,7 +158,7 @@ func DeleteClient(id string) error { func ReadClients() ([]*model.Client, error) { clients := make([]*model.Client, 0) - files, err := ioutil.ReadDir(filepath.Join(os.Getenv("WG_CLIENTS_DIR"))) + files, err := os.ReadDir(filepath.Join(os.Getenv("WG_CLIENTS_DIR"))) if err != nil { return nil, err } diff --git a/core/walletaddress.go b/core/node.go similarity index 88% rename from core/walletaddress.go rename to core/node.go index fa3e01d..3717244 100644 --- a/core/walletaddress.go +++ b/core/node.go @@ -17,37 +17,43 @@ import ( "golang.org/x/crypto/sha3" ) -var WalletAddress string +// These variables will be set at build time +var ( + Version string + CodeHash string +) -// GenerateWalletAddress generates a wallet address based on the environment variable set -func GenerateWalletAddress() { - // Check if MNEMONIC_ETH is set - if mnemonicEth := os.Getenv("MNEMONIC_ETH"); mnemonicEth != "" { - GenerateEthereumWalletAddress(mnemonicEth) - return - } +var NodeName string +var ChainName string +var NodeType string +var NodeConfig string - // Check if MNEMONIC_SOL is set - if mnemonicSol := os.Getenv("MNEMONIC_SOL"); mnemonicSol != "" { - GenerateWalletAddressSolana(mnemonicSol) - return - } +// Function to load the node details from the environment and save it to the global variable +func LoadNodeDetails() { + // Get the CHAIN_NAME variable from the environment + NodeName = os.Getenv("NODE_NAME") - // Check if MNEMONIC_APTOS is set - if mnemonicAptos := os.Getenv("MNEMONIC_APTOS"); mnemonicAptos != "" { - GenerateWalletAddressAptos(mnemonicAptos) - return + ChainName = os.Getenv("CHAIN_NAME") + if ChainName == "" { + log.Fatalf("CHAIN_NAME environment variable is not set") } + fmt.Printf("Chain Name: %s\n", ChainName) - // Check if MNEMONIC is set - if mnemonic := os.Getenv("MNEMONIC_SUI"); mnemonic != "" { - GenerateWalletAddressSui(mnemonic) - return + NodeType = os.Getenv("NODE_TYPE") + if NodeType == "" { + log.Fatalf("NODE_TYPE environment variable is not set") } + fmt.Printf("Node Type: %s\n", NodeType) - log.Fatal("No mnemonic environment variable is set") + NodeConfig = os.Getenv("NODE_CONFIG") + if NodeConfig == "" { + log.Fatalf("NODE_CONFIG environment variable is not set") + } + fmt.Printf("Node Config: %s\n", NodeConfig) } +var WalletAddress string + // GenerateEthereumWalletAddress generates an Ethereum wallet address from the given mnemonic func GenerateEthereumWalletAddress(mnemonic string) { // Validate the mnemonic diff --git a/core/server.go b/core/server.go index b8df92e..e734026 100644 --- a/core/server.go +++ b/core/server.go @@ -1,7 +1,6 @@ package core import ( - "bytes" "encoding/json" "errors" "io/ioutil" @@ -258,33 +257,3 @@ func MakeErrorResponse(status int64, err string, server *model.Server, client *m } } - -func UpdateEndpointDetails() { - for { - resp, err := http.Get("https://ipinfo.io/ip") - if err != nil { - log.WithFields(util.StandardFields).Fatal(err) - } - ip, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.WithFields(util.StandardFields).Fatal(err) - - } - var data model.RegionEndpoint - data.Code = os.Getenv("REGION_CODE") - data.Name = os.Getenv("REGION_NAME") - data.ServiceType = "erebrus" - data.Endpoint = string(ip) + ":" + os.Getenv("GRPC_PORT") - js, _ := json.Marshal(data) - - client := &http.Client{} - request, _ := http.NewRequest(http.MethodPatch, os.Getenv("MASTERNODE_URL")+"/api/v1.0/regupdate", bytes.NewBuffer(js)) - _, err = client.Do(request) - if err != nil { - log.WithFields(util.StandardFields).Fatal(err) - } - log.WithFields(util.StandardFields).Debug("Region Endpoint updation sucess") - time.Sleep(3 * time.Hour) - } - -} diff --git a/docker-compose.yml b/docker-compose.yml index ed5946b..694e652 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: SERVER: "0.0.0.0" PORT: "9080" HTTP_PORT: "8080" - MASTERNODE_URL: "https://masternode.erebrus.io" + GATEWAY_DOMAIN: "https://gateway.erebrus.io" WG_CONF_DIR: "/etc/wireguard" WG_KEYS_DIR: "/etc/wireguard/keys" WG_CLIENTS_DIR: "/etc/wireguard/clients" diff --git a/docs/deploy.md b/docs/deploy.md index e8027de..8d7e70e 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -1,116 +1,67 @@ - # Erebrus Deployment Docs - +## Build from Source +``` +go build -ldflags "-X main.version=1.0.0 -X main.codeHash=$(git rev-parse HEAD)" -o erebrus +``` ## Install and Deploy using binary - - 1. Make sure all setup were done - 2. Download the suitable binary for your operating system from [here](https://github.com/NetSepio/erebrus/releases/) - 3. create a .env file in same directory and define the environment for erebrus . you can use template from [.sample-env](https://github.com/NetSepio/erebrus/blob/main/.sample-env) - 4. Run - - ## Install and Deploy using Docker - - 1. Make sure all setup were done - 2. Pull the ererbus docker image - ``` - docker pull network/erebrus:latest - ``` - 3. Run the Image - ``` - docker run -d -p 9080:9080/tcp -p 51820:51820/udp --cap-add=NET_ADMIN --cap-add=SYS_MODULE --sysctl="net.ipv4.conf.all.src_valid_mark=1" --sysctl="net.ipv6.conf.all.forwarding=1" \ - -e LOAD_CONFIG_FILE="FALSE" \ - -e RUNTYPE='debug' \ - -e SERVER='0.0.0.0' \ - -e GRPC_PORT='9080' \ - -e WG_CONF_DIR='/etc/wireguard' \ - -e WG_KEYS_DIR='/etc/wireguard/keys' \ - -e WG_INTERFACE_NAME='wg0.conf' \ - -e WG_ENDPOINT_HOST='your endpoint' \ - -e WG_ENDPOINT_PORT='51820' \ - -e WG_IPv4_SUBNET='10.0.0.1/24' \ - -e WG_IPv6_SUBNET='fd9f:0000::10:0:0:1/64' \ - -e WG_DNS='1.1.1.1' \ - -e WG_ALLOWED_IP_1='0.0.0.0/0' \ - -e WG_ALLOWED_IP_2='::/0' \ - -e WG_PRE_UP='echo WireGuard PreUp' \ - -e WG_POST_UP='iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE' \ - -e WG_PRE_DOWN='echo WireGuard PreDown' \ - -e WG_POST_DOWN='iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE' \ - --restart unless-stopped \ - --name erebrus-region \ - erebrus - ``` - - or ``` - docker run -d -p 9080:9080/tcp -p 51820:51820/udp --cap-add=NET_ADMIN --cap-add=SYS_MODULE --sysctl="net.ipv4.conf.all.src_valid_mark=1" --sysctl="net.ipv6.conf.all.forwarding=1" --restart unless-stopped -v /home/ubuntu/erebrus/wireguard/:/etc/wireguard/ --name erebrus --env-file .env ghcr.io/netsepio/erebrus:main - ``` 4. Use the following commands - ``` - docker exec -it erebrus bash - ``` ``` - sudo netstat -pna | grep 51820 - ``` ``` - sudo lsof -i -P -n | grep 51820 - ``` ``` - docker rm -f $(docker ps -aq) - ``` \ No newline at end of file diff --git a/docs/node.md b/docs/node.md index 415945c..90d8b04 100644 --- a/docs/node.md +++ b/docs/node.md @@ -6,13 +6,14 @@ 2. create a .env file in same directory and define the environment for erebrus . you can use template from [.sample-env](https://github.com/NetSepio/erebrus/blob/main/.sample-env). Make sure to put the correct server URL. Example: ``` +NODE_NAME=blazing_icarus" DOMAIN=http://255.255.255.255:9080 HOST_IP=255.255.255.255 WG_ENDPOINT_HOST=255.255.255.255 ``` replace `255.255.255.255` with the server IP address -3. Open incoming request to ports: TCP Ports `9080`(http),` 9090`(gRPC),` 9001`(p2p) and UDP port `51820` of your server to communicate with the gateway +3. Open incoming request to ports: TCP Ports `9080`(http),` 9090`(gRPC),` 9002`(p2p) and UDP port `51820` of your server to communicate with the gateway 4. Pull the ererbus docker image ``` diff --git a/go.mod b/go.mod index ad33e4c..bbcbe13 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/libp2p/go-libp2p v0.33.2 github.com/libp2p/go-libp2p-kad-dht v0.25.2 github.com/libp2p/go-libp2p-pubsub v0.10.0 + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.3 github.com/patrickmn/go-cache v2.1.0+incompatible @@ -133,7 +134,6 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/ugorji/go/codec v1.2.9 // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect - github.com/xdg-go/pbkdf2 v1.0.0 go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect diff --git a/go.sum b/go.sum index c62e4db..8262d9a 100644 --- a/go.sum +++ b/go.sum @@ -316,6 +316,7 @@ github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUM github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -481,8 +482,6 @@ github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSD github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= -github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/install-node.sh b/install-node.sh index 75f1cb3..ee33ee5 100644 --- a/install-node.sh +++ b/install-node.sh @@ -335,10 +335,6 @@ configure_node() { fi done - - - - DEFAULT_HOST_IP=$(get_public_ip) DEFAULT_DOMAIN="http://${DEFAULT_HOST_IP}:9080" @@ -352,11 +348,25 @@ configure_node() { HOST_IP=${DEFAULT_HOST_IP} fi + # Prompt for Node Details + read -p "Enter your node name: " NODE_NAME + + # Prompt for Config Type + printf "Select a configuration type from list below:\n" + PS3="Select a config type (e.g. 1): " + options=("MINI" "STANDARD" "HPC") + select CONFIG in "${options[@]}"; do + if [ -n "$CONFIG" ]; then + break + else + echo "Invalid choice. Please select a valid config type." + fi + done # Prompt for Chain printf "Select valid chain from list below:\n" PS3="Select a chain (e.g. 1): " - options=("APT" "SOL" "EVM" "SUI" "SOON") + options=("SOLANA" "PEAQ" "APTOS" "SUI" "ECLIPSE") select CHAIN in "${options[@]}"; do if [ -n "$CHAIN" ]; then break @@ -374,38 +384,16 @@ configure_node() { fi done - # Prompt for chain selection - while true; do - read -p "Enter the chain (options: SOON, other): " chain - if [[ "$chain" == "SOON" || "$chain" == "other" ]]; then - break - else - printf "Invalid chain option. Please enter either 'SOON' or 'other'.\n" - fi - done - - # If 'SOON' is selected, ask for SOON_PRIVATE_KEY - if [[ "$chain" == "SOON" ]]; then - while true; do - read -p "Enter SOON_PRIVATE_KEY: " SOON_PRIVATE_KEY - if [[ -n "$SOON_PRIVATE_KEY" ]]; then - break - else - printf "SOON_PRIVATE_KEY cannot be empty. Please provide a valid key.\n" - fi - done - fi - # Display and confirm user-provided variables printf "\n\e[1mUser Provided Configuration:\e[0m\n" printf "INSTALL DIR=%s\n" "${INSTALL_DIR}" printf "REGION=$(get_region)\n" + printf "NODE_NAME=%s\n" "${NODE_NAME}" printf "HOST_IP=%s\n" "${HOST_IP}" printf "DOMAIN=%s\n" "${DEFAULT_DOMAIN}" printf "CHAIN=%s\n" "${CHAIN}" + printf "CONFIG=%s\n" "${CONFIG}" printf "MNEMONIC=%s\n" "${WALLET_MNEMONIC}" - printf "SOON_PRIVATE_KEY=%s\n" "${SOON_PRIVATE_KEY}" - read -p "Confirm configuration (y/n): " confirm if [ "${confirm}" != "y" ]; then @@ -423,29 +411,36 @@ configure_node() { # Write environment variables to .env file sudo tee ${INSTALL_DIR}/.env <