Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
variables:
STORAGE_DRIVER: vfs

container-build:
image: quay.io/buildah/stable:latest
before_script:
- buildah version
- export HOME=$CI_BUILDS_DIR # needed sometimes to avoid conflict with host
- buildah login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- env # tmp
- VERSION=$(git describe --always --abbrev=8 --dirty)
- echo buildah build -t $CI_PROJECT_NAME:$VERSION .
- buildah build -t $CI_PROJECT_NAME:$VERSION .
- echo buildah push $CI_PROJECT_NAME $CI_REGISTRY_IMAGE:$VERSION
- buildah push $CI_PROJECT_NAME $CI_REGISTRY_IMAGE:$VERSION

after_script:
- buildah logout $CI_REGISTRY
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# syntax=docker/dockerfile:1

FROM golang:1.17

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download
COPY *.go ./

RUN CGO_ENABLED=0 GOOS=linux go build -o /dtls_proxy

# These can be overriden via docker run -e foo=bar
ENV PSK_REST_ARG="https://localhost:12345"
ENV CONNECT_ARG="0.0.0.0:5683"
ENV BIND_ARG="0.0.0.0:5684"

CMD ["/bin/sh", "-c", "/dtls_proxy --connect $CONNECT_ARG --bind $BIND_ARG --psk-rest $PSK_REST_ARG"]
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,27 @@ architecture! The barrier of entry has never been lower! Yay!

## Key management integration

Iteration 1 of the proxy only supports the simplest KMS integration possible:
feeding the id/key pairs via a CSV file. Adding additional integrations (Redis,
SQL, etc) is just a matter of extending the `pskLookup()` function (patches more
than welcome).
Iteration 1 of the proxy only supported the simplest KMS integration possible:
feeding the id/key pairs via a CSV file.

Experimental REST support is also available:

```
./dtls_proxy ... --psk-rest http://$KMS_SRV:$KMS_PORT/keys
```

The KMS service needs to expect a query parameter of the form
`pskId=SOME_STRING`. If it requires additional query parameters (such as API
key), you can piggyback that onto the URL like this:

```
--psk-rest http://$KMS_SRV:$KMS_PORT/keys?apiKey=7ad2d94771c9f11f26a51223cb0d0608
```

or whatever -- the final request will include both the `pskId=SOME_STRING` part
and the `apiKey=7ad2d94771c9f11f26a51223cb0d0608` part. The PSK should be
returned in the body as raw binary data (no content-type checking or anything
like that is done by the DTLS proxy).

## DTLS Connection ID

Expand Down
87 changes: 77 additions & 10 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (
"flag"
"log"
"os"
"net/http"
"strings"
"io"

"github.com/pion/dtls/v2"
"github.com/pion/dtls/v2/examples/util"
Expand Down Expand Up @@ -65,7 +68,7 @@ func pipe(conn1 net.Conn, conn2 net.Conn) {
}
}

func pskLookup(pskId []byte, kms map[string][]byte) []byte {
func pskMapLookup(pskId []byte, kms map[string][]byte) []byte {
psk := kms[string(pskId)]
if psk == nil {
fmt.Printf("Client \"%s\" not found!\n", pskId)
Expand All @@ -76,6 +79,42 @@ func pskLookup(pskId []byte, kms map[string][]byte) []byte {
return psk
}

func pskRestLookup(pskId []byte, url string, extraQ string) []byte {
client := &http.Client{}

req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Print(err)
return nil
}

q := req.URL.Query()
q.Add("pskId", string(pskId))
if len(extraQ) > 0 {
splitExtraQ := strings.Split(extraQ, "=")
q.Add(splitExtraQ[0], splitExtraQ[1])
}

req.URL.RawQuery = q.Encode()

resp, err := client.Do(req)
if err != nil {
fmt.Print(err)
return nil
}

resBody, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Print(err)
return nil
}

fmt.Println("http response: ", resBody)

return resBody
}


func mapFromCsv(path string) map[string][]byte {
f, err := os.Open(path)
if err != nil {
Expand Down Expand Up @@ -104,8 +143,6 @@ func mapFromCsv(path string) map[string][]byte {
return m
}



func pskIdFromConn(conn net.Conn) string {
var dtlsConn *dtls.Conn = conn.(*dtls.Conn)
hint := string(dtlsConn.ConnectionState().IdentityHint)
Expand All @@ -116,20 +153,18 @@ func pskIdFromConn(conn net.Conn) string {
func main() {
bindPtr := flag.String("bind", "0.0.0.0:14881", "local ip:port to bind");
upsPtr := flag.String("connect", "kontor.eub.se:14999", "upstream plaintext ip:port")
csvPtr := flag.String("psk-csv", "keys.csv", "id/psk csv file")
csvPtr := flag.String("psk-csv", "", "id/psk csv file")
restPtr := flag.String("psk-rest", "", "id/psk rest looup uri")

flag.Parse()

fmt.Println("bind:", *bindPtr);
fmt.Println("ups:", *upsPtr);
fmt.Println("csv:", *csvPtr);

// Map between conns and PSK IDs, used to terminate stale connections
var connMap map[string]net.Conn
connMap = make(map[string]net.Conn)

kms := mapFromCsv(*csvPtr)

upstreamAddr := *upsPtr;

addr, err := net.ResolveUDPAddr("udp", *bindPtr);
Expand All @@ -146,12 +181,44 @@ func main() {
return context.WithTimeout(ctx, 30*time.Second)
},
ConnectionIDGenerator: dtls.RandomCIDGenerator(8),
PSK: func(hint []byte) ([]byte, error) {
return pskLookup(hint, kms), nil
},
CipherSuites: []dtls.CipherSuiteID{dtls.TLS_PSK_WITH_AES_128_CCM_8},
}

// If KMS lookup is via local csv, create a map from it
if len(*csvPtr) > 0 {
fmt.Println("csv:", *csvPtr);
kmsMap := mapFromCsv(*csvPtr);
config.PSK = func(hint []byte) ([]byte, error) {
return pskMapLookup(hint, kmsMap), nil
};
} else if len(*restPtr) > 0 {
fmt.Println("Targeting kms url:", *restPtr);

// Split into base and query param
var base string;
var xtra string;
split := strings.Split(*restPtr, "?")
if len(split) == 2 {
base = split[0];
xtra = split[1]
fmt.Println("url: ", base, " and ", xtra);
} else {
base = *restPtr;
xtra = "";
}

config.PSK = func(hint []byte) ([]byte, error) {
return pskRestLookup(hint, base, xtra), nil
};

} else {
fmt.Println("No KMS lookup method provided!");
os.Exit(1)
}




listener, err := dtls.Listen("udp", addr, config)
util.Check(err)
defer func() {
Expand Down