├── .appveyor.yml ├── .drone.yml ├── .github └── workflows │ └── go-test.yaml ├── Dockerfile ├── LICENSE.md ├── README.md ├── app.json ├── go.mod ├── go.sum ├── index.html ├── index_generate.go ├── index_generated.go ├── novnc_generate.go ├── novnc_generated.go ├── novnc_test.go ├── server.go ├── server_test.go └── wstcp ├── Dockerfile ├── README.md └── wstcp.go /.appveyor.yml: -------------------------------------------------------------------------------- 1 | image: ubuntu 2 | 3 | # stack: go 1.14 4 | 5 | version: '{build}' 6 | 7 | cache: 8 | - go1.14.deb 9 | 10 | install: 11 | - 'if [[ $APPVEYOR_REPO_TAG == "true" ]]; then appveyor UpdateBuild -Version "$(git describe --tags --always)"; else appveyor UpdateBuild -Version "$(git rev-parse --short HEAD)"; fi' 12 | - 'wget --no-clobber -O go1.14.deb https://deb.geek1011.net/pool/main/g/go/go_1.14-godeb1_amd64.deb || true' 13 | - sudo dpkg -i go1.14.deb 14 | - go mod download 15 | 16 | build_script: 17 | - go test -v ./... 18 | 19 | - GOOS=windows GOARCH=386 go build -o easy-novnc_windows.exe . 20 | - GOOS=darwin GOARCH=amd64 go build -o easy-novnc_darwin-64bit . 21 | - GOOS=linux GOARCH=386 go build -o easy-novnc_linux-32bit . 22 | - GOOS=linux GOARCH=amd64 go build -o easy-novnc_linux-64bit . 23 | - GOOS=linux GOARCH=arm go build -o easy-novnc_linux-arm . 24 | 25 | - GOOS=windows GOARCH=386 go build -o wstcp_windows.exe ./wstcp 26 | - GOOS=darwin GOARCH=amd64 go build -o wstcp_darwin-64bit ./wstcp 27 | - GOOS=linux GOARCH=386 go build -o wstcp_linux-32bit ./wstcp 28 | - GOOS=linux GOARCH=amd64 go build -o wstcp_linux-64bit ./wstcp 29 | - GOOS=linux GOARCH=arm go build -o wstcp_linux-arm ./wstcp 30 | 31 | test: off 32 | 33 | artifacts: 34 | - path: easy-novnc_* 35 | - path: wstcp_* 36 | 37 | deploy: 38 | release: $(APPVEYOR_BUILD_VERSION) 39 | provider: GitHub 40 | auth_token: 41 | secure: oMHoA3qAfCcz3PsfBJmce+fKcSOtUF1cTC3RUj1qKT4J4BjbkOcawazIrXR4F1eb 42 | artifact: /.+/ 43 | draft: true 44 | prerelease: false 45 | on: 46 | branch: master 47 | APPVEYOR_REPO_TAG: true -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: default 3 | 4 | steps: 5 | - name: test 6 | image: golang:1.14 7 | commands: 8 | - go mod download 9 | - go test -v ./... 10 | -------------------------------------------------------------------------------- /.github/workflows/go-test.yaml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | on: [push] 3 | jobs: 4 | 5 | build: 6 | name: Build 7 | runs-on: ubuntu-latest 8 | steps: 9 | 10 | - name: Set up Go 1.14 11 | uses: actions/setup-go@v1 12 | with: 13 | go-version: 1.14 14 | id: go 15 | 16 | - name: Check out code 17 | uses: actions/checkout@v1 18 | 19 | - name: Download dependencies 20 | run: go mod download 21 | 22 | - name: Run tests 23 | run: go test -v ./... 24 | 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.14-alpine AS build 2 | ADD . /src 3 | WORKDIR /src 4 | RUN apk add --no-cache git 5 | RUN go mod download 6 | RUN go build . 7 | 8 | FROM alpine:latest 9 | COPY --from=build /src/easy-novnc / 10 | EXPOSE 8080 11 | ENTRYPOINT ["/easy-novnc"] -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2020 Patrick G 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # easy-novnc 2 | An easy way to run a [noVNC](https://github.com/novnc/noVNC) instance and proxy with a single binary. 3 | 4 | ## Features 5 | - Clean start page. 6 | - CIDR whitelist/blacklist. 7 | - Optionally allow connections to arbitrary hosts (and ports). 8 | - Ensures the target port is a VNC server to prevent tunneling to unauthorized ports. 9 | - Can be configured using environment variables or command line flags (but works out-of-the box). 10 | - IPv6 support. 11 | - Single binary, no dependencies. 12 | - Easy setup. 13 | - Optional [client](./wstcp) for local TCP connections tunneled through WebSockets. 14 | 15 | ## Installation 16 | - Binaries for the latest commit can be downloaded [here](https://ci.appveyor.com/project/pgaskin/easy-novnc/build/artifacts). 17 | - It can also be [deployed to Heroku](https://heroku.com/deploy). 18 | - A Docker image is available: [geek1011/easy-novnc:latest](https://hub.docker.com/r/geek1011/easy-novnc). 19 | - You can build your own binaries with go 1.13 or newer using `go get github.com/pgaskin/easy-novnc` or by cloning this repo and running `go build`. 20 | 21 | ## Usage 22 | ``` 23 | Usage: easy-novnc [options] 24 | 25 | Options: 26 | -a, --addr string The address to listen on (env NOVNC_ADDR) (default ":8080") 27 | -H, --arbitrary-hosts Allow connection to other hosts (env NOVNC_ARBITRARY_HOSTS) 28 | -P, --arbitrary-ports Allow connections to arbitrary ports (requires arbitrary-hosts) (env NOVNC_ARBITRARY_PORTS) 29 | -u, --basic-ui Hide connection options from the main screen (env NOVNC_BASIC_UI) 30 | -C, --cidr-blacklist strings CIDR blacklist for when arbitrary hosts are enabled (comma separated) (conflicts with whitelist) (env NOVNC_CIDR_BLACKLIST) 31 | -c, --cidr-whitelist strings CIDR whitelist for when arbitrary hosts are enabled (comma separated) (conflicts with blacklist) (env NOVNC_CIDR_WHITELIST) 32 | --default-view-only Use view-only by default (env NOVNC_DEFAULT_VIEW_ONLY) 33 | --help Show this help text 34 | -h, --host string The host/ip to connect to by default (env NOVNC_HOST) (default "localhost") 35 | --no-url-password Do not allow password in URL params (env NOVNC_NO_URL_PASSWORD) 36 | -p, --port uint16 The port to connect to by default (env NOVNC_PORT) (default 5900) 37 | -v, --verbose Show extra log info (env NOVNC_VERBOSE) 38 | ``` 39 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy-novnc", 3 | "description": "An easy way to run a noVNC instance and proxy with a single binary.", 4 | "repository": "https://github.com/pgaskin/easy-novnc", 5 | "keywords": [ 6 | "novnc", 7 | "vnc", 8 | "websockify" 9 | ], 10 | "env": { 11 | "NOVNC_ARBITRARY_HOSTS": { 12 | "description": "Allow connection to other hosts", 13 | "value": "true" 14 | }, 15 | "NOVNC_ARBITRARY_PORTS": { 16 | "description": "Allow connections to arbitrary ports", 17 | "value": "true" 18 | }, 19 | "NOVNC_CIDR_WHITELIST": { 20 | "description": "CIDR whitelist for when arbitrary hosts are enabled (comma separated) (conflicts with blacklist)", 21 | "value": "" 22 | }, 23 | "NOVNC_CIDR_BLACKLIST": { 24 | "description": "CIDR blacklist for when arbitrary hosts are enabled (comma separated) (conflicts with blacklist)", 25 | "value": "" 26 | }, 27 | "NOVNC_BASIC_UI": { 28 | "description": "Hide connection options from the main screen", 29 | "value": "false" 30 | }, 31 | "NOVNC_HOST": { 32 | "description": "The host/ip to connect to by default", 33 | "value": "localhost" 34 | }, 35 | "NOVNC_PORT": { 36 | "description": "The port to connect to by default", 37 | "value": "5900" 38 | }, 39 | "NOVNC_NO_URL_PASSWORD": { 40 | "description": "Do not allow password in URL params", 41 | "value": "true" 42 | }, 43 | "NOVNC_PARAMS": { 44 | "description": "Extra URL params for noVNC (advanced) (comma separated key-value pairs) (e.g. resize=remote)", 45 | "value": "" 46 | }, 47 | "NOVNC_DEFAULT_VIEW_ONLY": { 48 | "description": "Use view-only by default", 49 | "value": "false" 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pgaskin/easy-novnc 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gorilla/mux v1.7.4 7 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 8 | github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd 9 | github.com/spf13/pflag v1.0.5 10 | github.com/spkg/zipfs v0.7.1 11 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a 12 | golang.org/x/tools v0.0.0-20200302213018-c4f5635f1074 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= 4 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 5 | github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= 6 | github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= 10 | github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 11 | github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0= 12 | github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= 13 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 14 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 15 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 16 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 17 | github.com/spkg/zipfs v0.7.0 h1:Ilog8m/WwtDM+Q0LS8Yjvl3S4mPKhE4WrtScIPUWmQw= 18 | github.com/spkg/zipfs v0.7.0/go.mod h1:48LW+/Rh1G7aAav1ew1PdlYn52T+LM+ARmSHfDNJvg8= 19 | github.com/spkg/zipfs v0.7.1 h1:+2X5lvNHTybnDMQZAIHgedRXZK1WXdc+94R/P5v2XWE= 20 | github.com/spkg/zipfs v0.7.1/go.mod h1:48LW+/Rh1G7aAav1ew1PdlYn52T+LM+ARmSHfDNJvg8= 21 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 22 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 23 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 24 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 25 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 26 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 27 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 28 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 29 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= 30 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 31 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= 32 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 33 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= 34 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 35 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 36 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 37 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 38 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 39 | golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f h1:ESK9Jb5JOE+y4u+ozMQeXfMHwEHm6zVbaDQkeaj6wI4= 40 | golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 41 | golang.org/x/tools v0.0.0-20200302213018-c4f5635f1074 h1:0nKaw3H/Gss/tnq0+jZzh6SiplGjXNDRfWFS85SiMtA= 42 | golang.org/x/tools v0.0.0-20200302213018-c4f5635f1074/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 43 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 44 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 45 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 |