-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b1f9edf
Showing
8 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# NetworkSimulator in Go | ||
|
||
Minimal network simulator written in Go. Inspired by [INetSim](https://www.inetsim.org/). | ||
|
||
**Features:** | ||
* Generate a CA certificate on start (you can import that as [trusted certificate authority](https://asu.secure.force.com/kb/articles/FAQ/How-Do-I-Add-Certificates-to-the-Trusted-Root-Certification-Authorities-Store-for-a-Local-Computer)) | ||
* Create DNS server on all addresses and respond to all queries with its own IP | ||
* Create HTTP server responding to all requests `200 OK` | ||
* Create HTTPs server responding to all requests `200 OK`. Generates on the fly server certificate (based on requested server name) | ||
|
||
## Thanks | ||
Shamelessly used following resources: | ||
* https://gist.github.com/walm/0d67b4fb2d5daf3edd4fad3e13b162cb | ||
* https://shaneutt.com/blog/golang-ca-and-signed-cert-go/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package main | ||
|
||
import ( | ||
"gonetsim/internal/dns" | ||
"gonetsim/internal/web" | ||
"log" | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
) | ||
|
||
func main() { | ||
dns.StartDNSServer(53) | ||
web.StartHttpServer(8080) | ||
web.StartHttpsServer(8443) | ||
sig := make(chan os.Signal) | ||
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) | ||
s := <-sig | ||
log.Fatalf("Signal (%v) received, stopping\n", s) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module gonetsim | ||
|
||
go 1.18 | ||
|
||
require ( | ||
github.com/miekg/dns v1.1.47 // indirect | ||
golang.org/x/mod v0.4.2 // indirect | ||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect | ||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect | ||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
github.com/miekg/dns v1.1.47 h1:J9bWiXbqMbnZPcY8Qi2E3EWIBsIm6MZzzJB9VRg5gL8= | ||
github.com/miekg/dns v1.1.47/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= | ||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= | ||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= | ||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= | ||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= | ||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package dns | ||
|
||
import ( | ||
"fmt" | ||
"github.com/miekg/dns" | ||
"log" | ||
"strconv" | ||
) | ||
|
||
func parseQuery(m *dns.Msg) { | ||
for _, q := range m.Question { | ||
switch q.Qtype { | ||
case dns.TypeA: | ||
log.Printf("Query for %s\n", q.Name) | ||
rr, err := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, "127.0.0.1")) | ||
if err == nil { | ||
m.Answer = append(m.Answer, rr) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) { | ||
m := new(dns.Msg) | ||
m.SetReply(r) | ||
m.Compress = false | ||
switch r.Opcode { | ||
case dns.OpcodeQuery: | ||
parseQuery(m) | ||
} | ||
w.WriteMsg(m) | ||
} | ||
|
||
func StartDNSServer(port int) { | ||
log.Printf("Starting DNS server at port %d\n", port) | ||
|
||
// attach request handler func | ||
dns.HandleFunc(".", handleDnsRequest) | ||
|
||
go func() { | ||
srv := &dns.Server{Addr: "127.0.0.1:" + strconv.Itoa(port), Net: "udp"} | ||
if err := srv.ListenAndServe(); err != nil { | ||
log.Fatalf("Failed to set udp listener %s\n", err.Error()) | ||
} | ||
defer srv.Shutdown() | ||
}() | ||
|
||
go func() { | ||
srv := &dns.Server{Addr: ":" + strconv.Itoa(port), Net: "tcp"} | ||
if err := srv.ListenAndServe(); err != nil { | ||
log.Fatalf("Failed to set tcp listener %s\n", err.Error()) | ||
} | ||
defer srv.Shutdown() | ||
}() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package web | ||
|
||
import ( | ||
"bytes" | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/tls" | ||
"crypto/x509" | ||
"crypto/x509/pkix" | ||
"encoding/pem" | ||
"log" | ||
"math/big" | ||
"time" | ||
) | ||
|
||
func GenerateCACertificate() (caCert *x509.Certificate, caBytes []byte, caKey *rsa.PrivateKey) { | ||
// set up our CA certificate | ||
ca := &x509.Certificate{ | ||
SerialNumber: big.NewInt(2019), | ||
Subject: pkix.Name{ | ||
Organization: []string{"Gonetsim"}, | ||
Country: []string{"CH"}, | ||
Province: []string{""}, | ||
Locality: []string{"Zurich"}, | ||
StreetAddress: []string{"Paradeplatz"}, | ||
PostalCode: []string{"8000"}, | ||
}, | ||
NotBefore: time.Now(), | ||
NotAfter: time.Now().AddDate(10, 0, 0), | ||
IsCA: true, | ||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, | ||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, | ||
BasicConstraintsValid: true, | ||
} | ||
|
||
// create our private and public key | ||
caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) | ||
if err != nil { | ||
log.Fatalf("Failed to generate CA key %s\n", err.Error()) | ||
} | ||
|
||
// create the CA | ||
caFinal, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey) | ||
if err != nil { | ||
log.Fatalf("Failed to generate CA certificate %s\n", err.Error()) | ||
} | ||
|
||
return ca, caFinal, caPrivKey | ||
} | ||
|
||
func SignCertificate(ca *x509.Certificate, caPrivKey *rsa.PrivateKey, certPrivKey *rsa.PrivateKey, commonName string) (serverTLSConf tls.Certificate) { | ||
|
||
// set up our server certificate | ||
cert := &x509.Certificate{ | ||
SerialNumber: big.NewInt(2019), | ||
Subject: pkix.Name{ | ||
CommonName: commonName, | ||
}, | ||
NotBefore: time.Now(), | ||
NotAfter: time.Now().AddDate(10, 0, 0), | ||
SubjectKeyId: []byte{1, 2, 3, 4, 6}, | ||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, | ||
KeyUsage: x509.KeyUsageDigitalSignature, | ||
} | ||
|
||
certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey) | ||
if err != nil { | ||
log.Fatalf("Failed to generate certificate %s\n", err.Error()) | ||
} | ||
|
||
certPEM := new(bytes.Buffer) | ||
pem.Encode(certPEM, &pem.Block{ | ||
Type: "CERTIFICATE", | ||
Bytes: certBytes, | ||
}) | ||
|
||
certPrivKeyPEM := new(bytes.Buffer) | ||
pem.Encode(certPrivKeyPEM, &pem.Block{ | ||
Type: "RSA PRIVATE KEY", | ||
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey), | ||
}) | ||
|
||
serverCert, err := tls.X509KeyPair(certPEM.Bytes(), certPrivKeyPEM.Bytes()) | ||
if err != nil { | ||
log.Fatalf("Failed to generate certificate keypair %s\n", err.Error()) | ||
} | ||
|
||
return serverCert | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package web | ||
|
||
import ( | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/tls" | ||
"crypto/x509" | ||
"encoding/pem" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
) | ||
|
||
func StartHttpServer(port int) { | ||
|
||
log.Printf("Starting HTTP server at port %d\n", port) | ||
|
||
http.HandleFunc("/", handleRequest()) | ||
|
||
go func() { | ||
if err := http.ListenAndServe(fmt.Sprint(":", port), nil); err != nil { | ||
log.Fatalf("Failed to start http server %s\n", err.Error()) | ||
} | ||
}() | ||
} | ||
|
||
func handleRequest() func(w http.ResponseWriter, r *http.Request) { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
w.WriteHeader(http.StatusOK) | ||
io.WriteString(w, "@_@\n") | ||
log.Printf("Responded to request %s %s%s", r.Method, r.Host, r.RequestURI) | ||
} | ||
} | ||
|
||
func StartHttpsServer(port int) { | ||
log.Printf("Starting HTTPs server at port %d\n", port) | ||
caCertificate, caBytes, caKey := GenerateCACertificate() | ||
|
||
caCert, _ := x509.ParseCertificate(caBytes) | ||
publicKeyDer, _ := x509.MarshalPKIXPublicKey(caCert.PublicKey) | ||
publicKeyBlock := pem.Block{ | ||
Type: "PUBLIC KEY", | ||
Bytes: publicKeyDer, | ||
} | ||
publicKeyPem := string(pem.EncodeToMemory(&publicKeyBlock)) | ||
log.Printf("CA Certificate (DER format):\n%s", publicKeyPem) | ||
|
||
// lets generate a key here and reuse it everytime! | ||
certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) | ||
if err != nil { | ||
log.Fatalf("Failed to generate caCertificate caKey %s\n", err.Error()) | ||
} | ||
|
||
serverTLSConf := &tls.Config{ | ||
GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { | ||
cert := SignCertificate(caCertificate, caKey, certPrivKey, info.ServerName) | ||
return &cert, nil | ||
}, | ||
} | ||
|
||
s := &http.Server{ | ||
Addr: fmt.Sprint(":", port), | ||
TLSConfig: serverTLSConf, | ||
} | ||
|
||
go func() { | ||
defer s.Close() | ||
if err := s.ListenAndServeTLS("", ""); err != nil { | ||
log.Fatalf("Failed to start HTTPS server %s\n", err.Error()) | ||
} | ||
}() | ||
} |