├── .github └── workflows │ └── main.yml ├── Dockerfile ├── README.md ├── config └── vpn_server.config ├── docker-compose.yml └── files └── start.sh /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Auto-CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the "master" branch 8 | push: 9 | branches: 10 | - '**' # every branch 11 | - '!stayactive' # except stayactive 12 | pull_request: 13 | branches: [ "master" ] 14 | schedule: 15 | - cron: '00 5 * * 6' # every Sunday at 5:00 16 | 17 | # Allows you to run this workflow manually from the Actions tab 18 | workflow_dispatch: 19 | 20 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 21 | jobs: 22 | stayactive: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - name: clone-update-push-delete 26 | env: 27 | PRIVKEY: ${{ secrets.PRIVKEY }} 28 | run: | 29 | # convert privkey to valid openssh privkey 30 | echo "$PRIVKEY" | tr ' ' '\n' > $GITHUB_WORKSPACE/customkey.orig 31 | echo -n > $GITHUB_WORKSPACE/customkey 32 | # first line 33 | cat $GITHUB_WORKSPACE/customkey.orig | head -n4 | tr '\n' ' ' | sed 's@ $@\n@g' >> $GITHUB_WORKSPACE/customkey 34 | # key content 35 | cat $GITHUB_WORKSPACE/customkey.orig | egrep -iv '(----|end|begin|openssh|private)' >> $GITHUB_WORKSPACE/customkey 36 | # last line 37 | cat $GITHUB_WORKSPACE/customkey.orig | tail -n-4 | tr '\n' ' ' | sed 's@ $@\n@g' >> $GITHUB_WORKSPACE/customkey 38 | # permission fix 39 | chmod 600 $GITHUB_WORKSPACE/customkey 40 | # git ssh param export 41 | export GIT_SSH_COMMAND="ssh -i $GITHUB_WORKSPACE/customkey -o StrictHostKeyChecking=no" 42 | # debug 43 | #cat $GITHUB_WORKSPACE/customkey | base64 44 | echo "Github repo: $GITHUB_REPOSITORY" 45 | git clone git@github.com:$GITHUB_REPOSITORY.git $GITHUB_WORKSPACE/code || { echo "git clone error"; exit 1; } 46 | cd $GITHUB_WORKSPACE/code || { echo "folder change problem"; exit 1; } 47 | git branch stayactive 48 | git checkout stayactive 49 | date >> status.txt 50 | git config user.name $GITHUB_REPOSITORY_OWNER 51 | git config user.email automation@dummy 52 | git add status.txt 53 | git commit -m "stay active" 54 | git push origin stayactive:stayactive || { echo "Stayactive branch push error"; exit 1; } 55 | git push origin -d stayactive || { echo "Stayactive branch delete error"; exit 1; } 56 | build-amd64: 57 | # The type of runner that the job will run on 58 | runs-on: ubuntu-latest 59 | # Steps represent a sequence of tasks that will be executed as part of the job 60 | steps: 61 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 62 | - uses: actions/checkout@v3 63 | - name: get latest url 64 | run: | 65 | BASE_URL="https://www.softether-download.com" 66 | LATEST_FOLDER=$( curl -s $BASE_URL/files/softether/ | tr ';' '\n' | grep -i href | awk -F'"' '{ print $2 }' | sort -n | tail -n1 ) 67 | echo "Latest folder is $LATEST_FOLDER" 68 | for FOLDER_STRING in "Intel_x64_or_AMD64" "ARM_64bit" 69 | do 70 | LATEST=$( curl -s "$BASE_URL/$LATEST_FOLDER/Linux/SoftEther_VPN_Server/64bit_-_$FOLDER_STRING/" | tr '<' '\n' | grep -i href | grep -i tar.gz | awk -F '"' '{ print $2 }' ) 71 | echo -e "\nURL for $FOLDER_STRING: " 72 | echo "$BASE_URL/$LATEST" | tee latest_url-$FOLDER_STRING.txt 73 | done 74 | - name: build image - AMD64 75 | env: 76 | ARCH: AMD64 77 | run: | 78 | LATEST_URL=$( cat latest_url-*$ARCH*.txt ) 79 | echo "Latest URL: $LATEST_URL" 80 | [ -z "$LATEST_URL" ] && { echo "Latest url not found"; exit 1; } 81 | curl -L -o files/softether.tar.gz "$LATEST_URL" || { echo "Softether download error"; exit 1; } 82 | ls -hal files/softether.tar.gz 83 | SOFTETHER_VERSION=$( basename $LATEST_URL | sed "s@softether-vpnserver-@@g" | cut -f1-3 -d'-' ) 84 | echo "Softether version: $SOFTETHER_VERSION" 85 | [ -z "$SOFTETHER_VERSION" ] && { echo "Softether version not defined"; exit 1; } 86 | echo -e "\n\nDockerfile:\n$( cat Dockerfile )\n\n" 87 | 88 | docker build --rm -t croc/softether . || { echo "Docker image build fail"; exit 1; } 89 | docker tag croc/softether croc/softether:$SOFTETHER_VERSION 90 | - name: push container 91 | env: 92 | DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} 93 | DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} 94 | run: | 95 | docker images 96 | echo "$DOCKERHUB_PASS" | docker login --username=$DOCKERHUB_USER --password-stdin 97 | docker images | grep -i softether 98 | # push latest images 99 | docker push croc/softether || { echo "latest image push error"; exit 1; } 100 | # push version 101 | VERSION=$( docker images | grep -i croc/softether | awk '{ print $2 }' | grep -i '^v' | sort | uniq ) 102 | echo "Image version: $VERSION" 103 | docker push croc/softether:$VERSION || { echo "version ($VERSION) image push error"; exit 1; } 104 | build-arm64: 105 | # The type of runner that the job will run on 106 | runs-on: ubuntu-latest 107 | # Steps represent a sequence of tasks that will be executed as part of the job 108 | steps: 109 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 110 | - uses: actions/checkout@v3 111 | - name: get latest url 112 | run: | 113 | BASE_URL="https://www.softether-download.com" 114 | LATEST_FOLDER=$( curl -s $BASE_URL/files/softether/ | tr ';' '\n' | grep -i href | awk -F'"' '{ print $2 }' | sort -n | tail -n1 ) 115 | echo "Latest folder is $LATEST_FOLDER" 116 | for FOLDER_STRING in "Intel_x64_or_AMD64" "ARM_64bit" 117 | do 118 | LATEST=$( curl -s "$BASE_URL/$LATEST_FOLDER/Linux/SoftEther_VPN_Server/64bit_-_$FOLDER_STRING/" | tr '<' '\n' | grep -i href | grep -i tar.gz | awk -F '"' '{ print $2 }' ) 119 | echo -e "\nURL for $FOLDER_STRING: " 120 | echo "$BASE_URL/$LATEST" | tee latest_url-$FOLDER_STRING.txt 121 | done 122 | - name: build and push image - ARM 64bit 123 | env: 124 | ARCH: ARM 125 | DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} 126 | DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} 127 | run: | 128 | LATEST_URL=$( cat latest_url-*$ARCH*.txt ) 129 | echo "Latest URL: $LATEST_URL" 130 | [ -z "$LATEST_URL" ] && { echo "Latest url not found"; exit 1; } 131 | curl -L -o files/softether.tar.gz "$LATEST_URL" || { echo "Softether download error"; exit 1; } 132 | ls -hal files/softether.tar.gz 133 | SOFTETHER_VERSION=$( basename $LATEST_URL | sed "s@softether-vpnserver-@@g" | cut -f1-3 -d'-' ) 134 | echo "Softether version: $SOFTETHER_VERSION" 135 | [ -z "$SOFTETHER_VERSION" ] && { echo "Softether version not defined"; exit 1; } 136 | echo -e "\n\nDockerfile:\n$( cat Dockerfile )\n\n" 137 | 138 | # create dockerhub login file 139 | echo '{ "auths": { "https://index.docker.io/v1/": { "auth": "---CHANGEME---" } } }' > config.json 140 | # debug: 141 | #echo -n "$DOCKERHUB_USER:$DOCKERHUB_PASS" | base64 142 | sed -i "s@---CHANGEME---@$( echo -n $DOCKERHUB_USER:$DOCKERHUB_PASS | base64 )@g" config.json 143 | # debug 144 | #cat config.json | base64 145 | 146 | # setup for kaniko multiarch build 147 | docker run --rm --privileged multiarch/qemu-user-static --reset -p yes || { echo "Multiarch setup error"; exit 1; } 148 | # build and push 149 | #docker run --rm -v $PWD:/workspace gcr.io/kaniko-project/executor --context /workspace --customPlatform linux/arm64/v8 --no-push || { echo "Build error"; exit 1; } 150 | docker run --rm -v $PWD:/workspace -v $PWD/config.json:/kaniko/.docker/config.json:ro gcr.io/kaniko-project/executor --context /workspace --customPlatform linux/arm64/v8 --destination=croc/softether-arm64:$SOFTETHER_VERSION --destination=croc/softether-arm64:latest || { echo "Build and push error"; exit 1; } 151 | 152 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:10 2 | 3 | RUN apt-get update -y && \ 4 | apt-get install -y curl tar gzip grep make gcc cpp 5 | 6 | COPY files/* /opt/ 7 | 8 | RUN tar xzfp /opt/softether.tar.gz -C /opt && \ 9 | rm -f /opt/softether.tar.gz 10 | RUN cd /opt/vpnserver && \ 11 | ls -hal && \ 12 | uname -a && cat /etc/os-release && \ 13 | make 14 | 15 | RUN chmod 755 /opt/start.sh 16 | 17 | #ENTRYPOINT /bin/bash 18 | ENTRYPOINT /opt/start.sh 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SoftEther 2 | 3 | My basic SoftEther VPN Server container. 4 | 5 | - https://www.softether.org 6 | 7 | # Usage 8 | 9 | The recommended way is docker-compose (with normal network mode). 10 | 11 | VERY IMPORTANT!: Create an empty config file with world-wide write permission under the config folder before start the server: 12 | ``` 13 | mkdir config 14 | touch config/vpn_server.config 15 | chmod 777 config/vpn_server.config 16 | ``` 17 | 18 | Start the container: 19 | 20 | ``` 21 | docker-compose up -d 22 | ``` 23 | 24 | # Remote Management 25 | 26 | - start the VPN server 27 | - connect to the server with SoftEther Server Manager Tool from Windows or macOS 28 | 29 | Notice: 30 | sometimes the default 443 port is used by another service, so use another available port like 5555, 8888... 31 | 32 | ## Configuration 33 | 34 | You can manage the VPN server from Windows with the Server Manager tool. Connect to the VPN server through 5555 TCP port. This is opened by default in docker-compose file. 35 | 36 | Do not worry. Any opened port accept every type of connection ( management, OpenVPN, etc). So you can use only one port if you like it. 37 | 38 | ### OpenVPN 39 | 40 | - Download the sample configuration files for OpenVPN clients (too) under the "OpenVPN/MS-SSTP Settings" with "Generate ..." button. 41 | - Use the `...openvpn_remote_access_l3.ovpn` file for clients (road warriors :) ) 42 | Do not forget! Change these parameters to your configuration in this sample file: 43 | ``` 44 | proto tcp 45 | remote vpn9999999999.v4.softether.net 5555 46 | ``` 47 | Upload the modified file to your clients and use it. 48 | 49 | 50 | 51 | Good Luck! 52 | -------------------------------------------------------------------------------- /config/vpn_server.config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crocandr/docker-softether/63ebac36a1c0b03e72d8ba2727b5a5e430fdf314/config/vpn_server.config -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | softether: 5 | image: croc/softether 6 | volumes: 7 | - './logs/packet_log:/opt/vpnserver/packet_log' 8 | - './logs/security_log:/opt/vpnserver/security_log' 9 | - './logs/server_log:/opt/vpnserver/server_log' 10 | - './config/backup.vpn_server.config:/opt/vpnserver/backup.vpn_server.config' 11 | - './config/chain_certs:/opt/vpnserver/chain_certs' 12 | - './config/vpn_server.config:/opt/vpnserver/vpn_server.config' 13 | - '/etc/localtime:/etc/localtime:ro' 14 | privileged: true 15 | # with host mode - maybe the services on vpn host is not accessible, like http, etc.. 16 | # network_mode: host 17 | # with normal mode - you cant add any local bridge, but every service on vpn host is accessible 18 | ports: 19 | - '5443:5443' 20 | - '5555:5555' 21 | - '55555:55555' 22 | restart: unless-stopped 23 | -------------------------------------------------------------------------------- /files/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BASE_DIR="/opt/vpnserver" 4 | 5 | # config file check 6 | [ -f $BASE_DIR/vpn_server.config ] || { echo "Config is not a file! Check your docker settings."; exit 1; } 7 | 8 | # first start 9 | if [ -s $BASE_DIR/vpn_server.config ] 10 | then 11 | echo "Config exists." 12 | else 13 | echo "Config not exists, creating a basic configuration..." 14 | $BASE_DIR/vpnserver start 15 | sleep 2 16 | $BASE_DIR/vpnserver stop 17 | # basic config for remote management 18 | $BASE_DIR/vpncmd RemoteEnable 19 | fi 20 | 21 | # start vpn service 22 | $BASE_DIR/vpnserver start 23 | 24 | # something daemon like stuff 25 | [ $( ls -1 $BASE_DIR/server_log/* | wc -l ) -gt 0 ] && { tail -f $BASE_DIR/server_log/*; } || { echo "sorry, log file not found"; tail -f /dev/null; } 26 | --------------------------------------------------------------------------------