mirror of
https://github.com/fatedier/frp.git
synced 2026-03-30 05:39:16 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa0a41ee4e | ||
|
|
8a779eb88c | ||
|
|
0138dbd352 | ||
|
|
9b45c93c14 | ||
|
|
191da54980 | ||
|
|
c3b7575453 | ||
|
|
1ea1530b36 | ||
|
|
7f7305fa03 | ||
|
|
644a0cfdb6 | ||
|
|
3c2e2bcea5 |
29
.github/ISSUE_TEMPLATE
vendored
29
.github/ISSUE_TEMPLATE
vendored
@@ -1,29 +0,0 @@
|
|||||||
Issue is only used for submiting bug report and documents typo. If there are same issues or answers can be found in documents, we will close it directly.
|
|
||||||
|
|
||||||
Use the commands below to provide key information from your environment:
|
|
||||||
You do NOT have to include this information if this is a FEATURE REQUEST
|
|
||||||
|
|
||||||
**What version of frp are you using (./frpc -v or ./frps -v)?**
|
|
||||||
|
|
||||||
|
|
||||||
**What operating system and processor architecture are you using (`go env`)?**
|
|
||||||
|
|
||||||
|
|
||||||
**Configures you used:**
|
|
||||||
|
|
||||||
|
|
||||||
**Steps to reproduce the issue:**
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
|
|
||||||
**Describe the results you received:**
|
|
||||||
|
|
||||||
|
|
||||||
**Describe the results you expected:**
|
|
||||||
|
|
||||||
|
|
||||||
**Additional information you deem important (e.g. issue happens only occasionally):**
|
|
||||||
|
|
||||||
|
|
||||||
**Can you point out what caused this issue (optional)**
|
|
||||||
44
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
44
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Bug Report for FRP
|
||||||
|
title: ''
|
||||||
|
labels: Requires Testing
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- From Chinese to English by machine translation, welcome to revise and polish. -->
|
||||||
|
|
||||||
|
<!-- ⚠️⚠️ Incomplete reports will be marked as invalid, and closed, with few exceptions ⚠️⚠️ -->
|
||||||
|
<!-- in addition, please use search well so that the same solution can be found in the feedback, we will close it directly -->
|
||||||
|
<!-- for convenience of differentiation, use FRPS or FRPC to refer to the FRP server or client -->
|
||||||
|
|
||||||
|
**[REQUIRED] hat version of frp are you using**
|
||||||
|
<!-- Use ./frpc -v or ./frps -v -->
|
||||||
|
Version:
|
||||||
|
|
||||||
|
**[REQUIRED] What operating system and processor architecture are you using**
|
||||||
|
OS:
|
||||||
|
CPU architecture:
|
||||||
|
|
||||||
|
**[REQUIRED] description of errors**
|
||||||
|
|
||||||
|
**confile**
|
||||||
|
<!-- Please pay attention to hiding the token, server_addr and other privacy information -->
|
||||||
|
|
||||||
|
**log file**
|
||||||
|
<!-- If the file is too large, use Pastebin, for example https://pastebin.ubuntu.com/ -->
|
||||||
|
|
||||||
|
**Steps to reproduce the issue**
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
**Supplementary information**
|
||||||
|
|
||||||
|
**Can you guess what caused this issue**
|
||||||
|
|
||||||
|
**Checklist**:
|
||||||
|
<!--- Make sure you've completed the following steps (put an "X" between of brackets): -->
|
||||||
|
- [] I included all information required in the sections above
|
||||||
|
- [] I made sure there are no duplicates of this report [(Use Search)](https://github.com/fatedier/frp/issues?q=is%3Aissue)
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: DOCS
|
||||||
|
url: https://github.com/fatedier/frp
|
||||||
|
about: Here you can find out how to configure frp.
|
||||||
22
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
22
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: "[+] Enhancement"
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- From Chinese to English by machine translation, welcome to revise and polish. -->
|
||||||
|
|
||||||
|
**The solution you want**
|
||||||
|
<!--A clear and concise description of the solution you want. -->
|
||||||
|
|
||||||
|
**Alternatives considered**
|
||||||
|
<!--A clear and concise description of any alternative solutions or features you have considered. -->
|
||||||
|
|
||||||
|
**How to implement this function**
|
||||||
|
<!--Implementation steps for the solution you want. -->
|
||||||
|
|
||||||
|
**Application scenarios of this function**
|
||||||
|
<!--Make a clear and concise description of the application scenario of the solution you want. -->
|
||||||
32
.github/workflows/build-and-push-image.yml
vendored
32
.github/workflows/build-and-push-image.yml
vendored
@@ -75,41 +75,41 @@ jobs:
|
|||||||
name: Get Image Tag Name
|
name: Get Image Tag Name
|
||||||
run: |
|
run: |
|
||||||
if [ x${{ github.event.inputs.tag }} == x"" ]; then
|
if [ x${{ github.event.inputs.tag }} == x"" ]; then
|
||||||
echo ::set-env name=TAG_NAME::${GITHUB_REF#refs/*/}
|
echo "TAG_NAME=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
echo ::set-env name=TAG_NAME::${{ github.event.inputs.tag }}
|
echo "TAG_NAME=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
# prepare image tags
|
# prepare image tags
|
||||||
-
|
-
|
||||||
name: Prepare Image Tags
|
name: Prepare Image Tags
|
||||||
run: |
|
run: |
|
||||||
echo ::set-env name=DOCKERFILE_FRPC_PATH::dockerfiles/Dockerfile-for-frpc
|
echo "DOCKERFILE_FRPC_PATH=dockerfiles/Dockerfile-for-frpc" >> $GITHUB_ENV
|
||||||
echo ::set-env name=DOCKERFILE_FRPS_PATH::dockerfiles/Dockerfile-for-frps
|
echo "DOCKERFILE_FRPS_PATH=dockerfiles/Dockerfile-for-frps" >> $GITHUB_ENV
|
||||||
echo ::set-env name=TAG_FRPC::fatedier/frpc:$TAG_NAME
|
echo "TAG_FRPC=fatedier/frpc:${{ env.TAG_NAME }}" >> $GITHUB_ENV
|
||||||
echo ::set-env name=TAG_FRPS::fatedier/frps:$TAG_NAME
|
echo "TAG_FRPS=fatedier/frps:${{ env.TAG_NAME }}" >> $GITHUB_ENV
|
||||||
echo ::set-env name=TAG_FRPC_GPR::ghcr.io/fatedier/frpc:$TAG_NAME
|
echo "TAG_FRPC_GPR=ghcr.io/fatedier/frpc:${{ env.TAG_NAME }}" >> $GITHUB_ENV
|
||||||
echo ::set-env name=TAG_FRPS_GPR::ghcr.io/fatedier/frps:$TAG_NAME
|
echo "TAG_FRPS_GPR=ghcr.io/fatedier/frps:${{ env.TAG_NAME }}" >> $GITHUB_ENV
|
||||||
# build images
|
# build images
|
||||||
-
|
-
|
||||||
name: Build Images
|
name: Build Images
|
||||||
run: |
|
run: |
|
||||||
# for Docker hub
|
# for Docker hub
|
||||||
docker build --file $DOCKERFILE_FRPC_PATH --tag $TAG_FRPC .
|
docker build --file ${{ env.DOCKERFILE_FRPC_PATH }} --tag ${{ env.TAG_FRPC }} .
|
||||||
docker build --file $DOCKERFILE_FRPS_PATH --tag $TAG_FRPS .
|
docker build --file ${{ env.DOCKERFILE_FRPS_PATH }} --tag ${{ env.TAG_FRPS }} .
|
||||||
# for GPR
|
# for GPR
|
||||||
docker build --file $DOCKERFILE_FRPC_PATH --tag $TAG_FRPC_GPR .
|
docker build --file ${{ env.DOCKERFILE_FRPC_PATH }} --tag ${{ env.TAG_FRPC_GPR }} .
|
||||||
docker build --file $DOCKERFILE_FRPS_PATH --tag $TAG_FRPS_GPR .
|
docker build --file ${{ env.DOCKERFILE_FRPS_PATH }} --tag ${{ env.TAG_FRPS_GPR }} .
|
||||||
# push to dockerhub
|
# push to dockerhub
|
||||||
-
|
-
|
||||||
name: Publish to Dockerhub
|
name: Publish to Dockerhub
|
||||||
run: |
|
run: |
|
||||||
echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login --username ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
|
echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login --username ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
|
||||||
docker push $TAG_FRPC
|
docker push ${{ env.TAG_FRPC }}
|
||||||
docker push $TAG_FRPS
|
docker push ${{ env.TAG_FRPS }}
|
||||||
# push to gpr
|
# push to gpr
|
||||||
-
|
-
|
||||||
name: Publish to GPR
|
name: Publish to GPR
|
||||||
run: |
|
run: |
|
||||||
echo ${{ secrets.GPR_TOKEN }} | docker login ghcr.io --username ${{ github.repository_owner }} --password-stdin
|
echo ${{ secrets.GPR_TOKEN }} | docker login ghcr.io --username ${{ github.repository_owner }} --password-stdin
|
||||||
docker push $TAG_FRPC_GPR
|
docker push ${{ env.TAG_FRPC_GPR }}
|
||||||
docker push $TAG_FRPS_GPR
|
docker push ${{ env.TAG_FRPS_GPR }}
|
||||||
|
|||||||
30
.github/workflows/goreleaser.yml
vendored
Normal file
30
.github/workflows/goreleaser.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: goreleaser
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.15
|
||||||
|
|
||||||
|
- name: Make All
|
||||||
|
run: |
|
||||||
|
./package.sh
|
||||||
|
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: release --rm-dist --release-notes=./Release.md
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,6 +29,7 @@ packages/
|
|||||||
release/
|
release/
|
||||||
test/bin/
|
test/bin/
|
||||||
vendor/
|
vendor/
|
||||||
|
dist/
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
*.swp
|
*.swp
|
||||||
|
|||||||
19
.goreleaser.yml
Normal file
19
.goreleaser.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
builds:
|
||||||
|
- skip: true
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
release:
|
||||||
|
# Same as for github
|
||||||
|
# Note: it can only be one: either github, gitlab or gitea
|
||||||
|
github:
|
||||||
|
owner: fatedier
|
||||||
|
name: frp
|
||||||
|
|
||||||
|
draft: false
|
||||||
|
|
||||||
|
# You can add extra pre-existing files to the release.
|
||||||
|
# The filename on the release will be the last part of the path (base). If
|
||||||
|
# another file with the same name exists, the latest one found will be used.
|
||||||
|
# Defaults to empty.
|
||||||
|
extra_files:
|
||||||
|
- glob: ./release/packages/*
|
||||||
@@ -2,8 +2,8 @@ sudo: false
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.13.x
|
|
||||||
- 1.14.x
|
- 1.14.x
|
||||||
|
- 1.15.x
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- make
|
- make
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -20,10 +20,10 @@ fmt:
|
|||||||
go fmt ./...
|
go fmt ./...
|
||||||
|
|
||||||
frps:
|
frps:
|
||||||
env CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" -o bin/frps ./cmd/frps
|
env CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o bin/frps ./cmd/frps
|
||||||
|
|
||||||
frpc:
|
frpc:
|
||||||
env CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" -o bin/frpc ./cmd/frpc
|
env CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o bin/frpc ./cmd/frpc
|
||||||
|
|
||||||
test: gotest
|
test: gotest
|
||||||
|
|
||||||
|
|||||||
@@ -7,32 +7,29 @@ all: build
|
|||||||
build: app
|
build: app
|
||||||
|
|
||||||
app:
|
app:
|
||||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_darwin_amd64 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_darwin_amd64 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_darwin_amd64 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_darwin_amd64 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_freebsd_386 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_freebsd_386 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps_freebsd_386 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_freebsd_386 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_freebsd_amd64 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_freebsd_amd64 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_freebsd_amd64 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_freebsd_amd64 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_386 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_386 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_386 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_386 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_amd64 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_amd64 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_amd64 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_amd64 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_arm ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_arm ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_arm ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_arm ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_arm64 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_arm64 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_arm64 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_arm64 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_windows_386.exe ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_windows_386.exe ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps_windows_386.exe ./cmd/frps
|
env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_windows_386.exe ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_windows_amd64.exe ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_windows_amd64.exe ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_windows_amd64.exe ./cmd/frps
|
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_windows_amd64.exe ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips64 ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips64 ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips64 ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips64 ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips64le ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips64le ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips64le ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips64le ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips ./cmd/frps
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mipsle ./cmd/frpc
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mipsle ./cmd/frpc
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mipsle ./cmd/frps
|
env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -trimpath -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mipsle ./cmd/frps
|
||||||
|
|
||||||
temp:
|
|
||||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frps_linux_amd64 ./cmd/frps
|
|
||||||
|
|||||||
3
Release.md
Normal file
3
Release.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### New
|
||||||
|
|
||||||
|
* Command line parameters support `enable_prometheus`.
|
||||||
@@ -49,6 +49,7 @@ var (
|
|||||||
dashboardPort int
|
dashboardPort int
|
||||||
dashboardUser string
|
dashboardUser string
|
||||||
dashboardPwd string
|
dashboardPwd string
|
||||||
|
enablePrometheus bool
|
||||||
assetsDir string
|
assetsDir string
|
||||||
logFile string
|
logFile string
|
||||||
logLevel string
|
logLevel string
|
||||||
@@ -79,6 +80,7 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().IntVarP(&dashboardPort, "dashboard_port", "", 0, "dashboard port")
|
rootCmd.PersistentFlags().IntVarP(&dashboardPort, "dashboard_port", "", 0, "dashboard port")
|
||||||
rootCmd.PersistentFlags().StringVarP(&dashboardUser, "dashboard_user", "", "admin", "dashboard user")
|
rootCmd.PersistentFlags().StringVarP(&dashboardUser, "dashboard_user", "", "admin", "dashboard user")
|
||||||
rootCmd.PersistentFlags().StringVarP(&dashboardPwd, "dashboard_pwd", "", "admin", "dashboard password")
|
rootCmd.PersistentFlags().StringVarP(&dashboardPwd, "dashboard_pwd", "", "admin", "dashboard password")
|
||||||
|
rootCmd.PersistentFlags().BoolVarP(&enablePrometheus, "enable_prometheus", "", false, "enable prometheus dashboard")
|
||||||
rootCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "log file")
|
rootCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "log file")
|
||||||
rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
|
rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
|
||||||
rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log max days")
|
rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log max days")
|
||||||
@@ -171,6 +173,7 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
|
|||||||
cfg.DashboardPort = dashboardPort
|
cfg.DashboardPort = dashboardPort
|
||||||
cfg.DashboardUser = dashboardUser
|
cfg.DashboardUser = dashboardUser
|
||||||
cfg.DashboardPwd = dashboardPwd
|
cfg.DashboardPwd = dashboardPwd
|
||||||
|
cfg.EnablePrometheus = enablePrometheus
|
||||||
cfg.LogFile = logFile
|
cfg.LogFile = logFile
|
||||||
cfg.LogLevel = logLevel
|
cfg.LogLevel = logLevel
|
||||||
cfg.LogMaxDays = logMaxDays
|
cfg.LogMaxDays = logMaxDays
|
||||||
|
|||||||
@@ -22,7 +22,14 @@ log_max_days = 3
|
|||||||
# disable log colors when log_file is console, default is false
|
# disable log colors when log_file is console, default is false
|
||||||
disable_log_color = false
|
disable_log_color = false
|
||||||
|
|
||||||
# for authentication
|
# for authentication, should be same as your frps.ini
|
||||||
|
# AuthenticateHeartBeats specifies whether to include authentication token in heartbeats sent to frps. By default, this value is false.
|
||||||
|
authenticate_heartbeats = false
|
||||||
|
|
||||||
|
# AuthenticateNewWorkConns specifies whether to include authentication token in new work connections sent to frps. By default, this value is false.
|
||||||
|
authenticate_new_work_conns = false
|
||||||
|
|
||||||
|
# auth token
|
||||||
token = 12345678
|
token = 12345678
|
||||||
|
|
||||||
# set admin address for control frpc's action by http api such as reload
|
# set admin address for control frpc's action by http api such as reload
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module github.com/fatedier/frp
|
module github.com/fatedier/frp
|
||||||
|
|
||||||
go 1.12
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version string = "0.34.1"
|
var version string = "0.34.3"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -24,6 +25,19 @@ import (
|
|||||||
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
// ReverseProxy is an HTTP Handler that takes an incoming request and
|
||||||
// sends it to another server, proxying the response back to the
|
// sends it to another server, proxying the response back to the
|
||||||
// client.
|
// client.
|
||||||
|
//
|
||||||
|
// ReverseProxy by default sets the client IP as the value of the
|
||||||
|
// X-Forwarded-For header.
|
||||||
|
//
|
||||||
|
// If an X-Forwarded-For header already exists, the client IP is
|
||||||
|
// appended to the existing values. As a special case, if the header
|
||||||
|
// exists in the Request.Header map but has a nil value (such as when
|
||||||
|
// set by the Director func), the X-Forwarded-For header is
|
||||||
|
// not modified.
|
||||||
|
//
|
||||||
|
// To prevent IP spoofing, be sure to delete any pre-existing
|
||||||
|
// X-Forwarded-For header coming from the client or
|
||||||
|
// an untrusted proxy.
|
||||||
type ReverseProxy struct {
|
type ReverseProxy struct {
|
||||||
// Director must be a function which modifies
|
// Director must be a function which modifies
|
||||||
// the request into a new request to be sent
|
// the request into a new request to be sent
|
||||||
@@ -44,9 +58,9 @@ type ReverseProxy struct {
|
|||||||
// A negative value means to flush immediately
|
// A negative value means to flush immediately
|
||||||
// after each write to the client.
|
// after each write to the client.
|
||||||
// The FlushInterval is ignored when ReverseProxy
|
// The FlushInterval is ignored when ReverseProxy
|
||||||
// recognizes a response as a streaming response;
|
// recognizes a response as a streaming response, or
|
||||||
// for such responses, writes are flushed to the client
|
// if its ContentLength is -1; for such responses, writes
|
||||||
// immediately.
|
// are flushed to the client immediately.
|
||||||
FlushInterval time.Duration
|
FlushInterval time.Duration
|
||||||
|
|
||||||
// ErrorLog specifies an optional logger for errors
|
// ErrorLog specifies an optional logger for errors
|
||||||
@@ -97,6 +111,27 @@ func singleJoiningSlash(a, b string) string {
|
|||||||
return a + b
|
return a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func joinURLPath(a, b *url.URL) (path, rawpath string) {
|
||||||
|
if a.RawPath == "" && b.RawPath == "" {
|
||||||
|
return singleJoiningSlash(a.Path, b.Path), ""
|
||||||
|
}
|
||||||
|
// Same as singleJoiningSlash, but uses EscapedPath to determine
|
||||||
|
// whether a slash should be added
|
||||||
|
apath := a.EscapedPath()
|
||||||
|
bpath := b.EscapedPath()
|
||||||
|
|
||||||
|
aslash := strings.HasSuffix(apath, "/")
|
||||||
|
bslash := strings.HasPrefix(bpath, "/")
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case aslash && bslash:
|
||||||
|
return a.Path + b.Path[1:], apath + bpath[1:]
|
||||||
|
case !aslash && !bslash:
|
||||||
|
return a.Path + "/" + b.Path, apath + "/" + bpath
|
||||||
|
}
|
||||||
|
return a.Path + b.Path, apath + bpath
|
||||||
|
}
|
||||||
|
|
||||||
// NewSingleHostReverseProxy returns a new ReverseProxy that routes
|
// NewSingleHostReverseProxy returns a new ReverseProxy that routes
|
||||||
// URLs to the scheme, host, and base path provided in target. If the
|
// URLs to the scheme, host, and base path provided in target. If the
|
||||||
// target's path is "/base" and the incoming request was for "/dir",
|
// target's path is "/base" and the incoming request was for "/dir",
|
||||||
@@ -109,7 +144,7 @@ func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
|
|||||||
director := func(req *http.Request) {
|
director := func(req *http.Request) {
|
||||||
req.URL.Scheme = target.Scheme
|
req.URL.Scheme = target.Scheme
|
||||||
req.URL.Host = target.Host
|
req.URL.Host = target.Host
|
||||||
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
|
req.URL.Path, req.URL.RawPath = joinURLPath(target, req.URL)
|
||||||
if targetQuery == "" || req.URL.RawQuery == "" {
|
if targetQuery == "" || req.URL.RawQuery == "" {
|
||||||
req.URL.RawQuery = targetQuery + req.URL.RawQuery
|
req.URL.RawQuery = targetQuery + req.URL.RawQuery
|
||||||
} else {
|
} else {
|
||||||
@@ -195,16 +230,19 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
outreq := req.WithContext(ctx)
|
outreq := req.Clone(ctx)
|
||||||
if req.ContentLength == 0 {
|
if req.ContentLength == 0 {
|
||||||
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
|
||||||
}
|
}
|
||||||
|
if outreq.Header == nil {
|
||||||
|
outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
|
||||||
|
}
|
||||||
|
|
||||||
// =============================
|
// =============================
|
||||||
// Modified for frp
|
// Modified for frp
|
||||||
outreq = outreq.WithContext(context.WithValue(outreq.Context(), RouteInfoURL, req.URL.Path))
|
outreq = outreq.Clone(context.WithValue(outreq.Context(), RouteInfoURL, req.URL.Path))
|
||||||
outreq = outreq.WithContext(context.WithValue(outreq.Context(), RouteInfoHost, req.Host))
|
outreq = outreq.Clone(context.WithValue(outreq.Context(), RouteInfoHost, req.Host))
|
||||||
outreq = outreq.WithContext(context.WithValue(outreq.Context(), RouteInfoRemote, req.RemoteAddr))
|
outreq = outreq.Clone(context.WithValue(outreq.Context(), RouteInfoRemote, req.RemoteAddr))
|
||||||
// =============================
|
// =============================
|
||||||
|
|
||||||
p.Director(outreq)
|
p.Director(outreq)
|
||||||
@@ -244,10 +282,14 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
// If we aren't the first proxy retain prior
|
// If we aren't the first proxy retain prior
|
||||||
// X-Forwarded-For information as a comma+space
|
// X-Forwarded-For information as a comma+space
|
||||||
// separated list and fold multiple headers into one.
|
// separated list and fold multiple headers into one.
|
||||||
if prior, ok := outreq.Header["X-Forwarded-For"]; ok {
|
prior, ok := outreq.Header["X-Forwarded-For"]
|
||||||
|
omit := ok && prior == nil // Issue 38079: nil now means don't populate the header
|
||||||
|
if len(prior) > 0 {
|
||||||
clientIP = strings.Join(prior, ", ") + ", " + clientIP
|
clientIP = strings.Join(prior, ", ") + ", " + clientIP
|
||||||
}
|
}
|
||||||
outreq.Header.Set("X-Forwarded-For", clientIP)
|
if !omit {
|
||||||
|
outreq.Header.Set("X-Forwarded-For", clientIP)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := transport.RoundTrip(outreq)
|
res, err := transport.RoundTrip(outreq)
|
||||||
@@ -290,7 +332,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
rw.WriteHeader(res.StatusCode)
|
rw.WriteHeader(res.StatusCode)
|
||||||
|
|
||||||
err = p.copyResponse(rw, res.Body, p.flushInterval(req, res))
|
err = p.copyResponse(rw, res.Body, p.flushInterval(res))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
// Since we're streaming the response, if we run into an error all we can do
|
// Since we're streaming the response, if we run into an error all we can do
|
||||||
@@ -353,7 +395,7 @@ func shouldPanicOnCopyError(req *http.Request) bool {
|
|||||||
func removeConnectionHeaders(h http.Header) {
|
func removeConnectionHeaders(h http.Header) {
|
||||||
for _, f := range h["Connection"] {
|
for _, f := range h["Connection"] {
|
||||||
for _, sf := range strings.Split(f, ",") {
|
for _, sf := range strings.Split(f, ",") {
|
||||||
if sf = strings.TrimSpace(sf); sf != "" {
|
if sf = textproto.TrimString(sf); sf != "" {
|
||||||
h.Del(sf)
|
h.Del(sf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,7 +404,7 @@ func removeConnectionHeaders(h http.Header) {
|
|||||||
|
|
||||||
// flushInterval returns the p.FlushInterval value, conditionally
|
// flushInterval returns the p.FlushInterval value, conditionally
|
||||||
// overriding its value for a specific request/response.
|
// overriding its value for a specific request/response.
|
||||||
func (p *ReverseProxy) flushInterval(req *http.Request, res *http.Response) time.Duration {
|
func (p *ReverseProxy) flushInterval(res *http.Response) time.Duration {
|
||||||
resCT := res.Header.Get("Content-Type")
|
resCT := res.Header.Get("Content-Type")
|
||||||
|
|
||||||
// For Server-Sent Events responses, flush immediately.
|
// For Server-Sent Events responses, flush immediately.
|
||||||
@@ -371,7 +413,11 @@ func (p *ReverseProxy) flushInterval(req *http.Request, res *http.Response) time
|
|||||||
return -1 // negative means immediately
|
return -1 // negative means immediately
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: more specific cases? e.g. res.ContentLength == -1?
|
// We might have the case of streaming for which Content-Length might be unset.
|
||||||
|
if res.ContentLength == -1 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
return p.FlushInterval
|
return p.FlushInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,8 +556,6 @@ func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.R
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
copyHeader(res.Header, rw.Header())
|
|
||||||
|
|
||||||
hj, ok := rw.(http.Hijacker)
|
hj, ok := rw.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw))
|
p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw))
|
||||||
@@ -522,13 +566,30 @@ func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.R
|
|||||||
p.getErrorHandler()(rw, req, fmt.Errorf("internal error: 101 switching protocols response with non-writable body"))
|
p.getErrorHandler()(rw, req, fmt.Errorf("internal error: 101 switching protocols response with non-writable body"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer backConn.Close()
|
|
||||||
|
backConnCloseCh := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
// Ensure that the cancelation of a request closes the backend.
|
||||||
|
// See issue https://golang.org/issue/35559.
|
||||||
|
select {
|
||||||
|
case <-req.Context().Done():
|
||||||
|
case <-backConnCloseCh:
|
||||||
|
}
|
||||||
|
backConn.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer close(backConnCloseCh)
|
||||||
|
|
||||||
conn, brw, err := hj.Hijack()
|
conn, brw, err := hj.Hijack()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("Hijack failed on protocol switch: %v", err))
|
p.getErrorHandler()(rw, req, fmt.Errorf("Hijack failed on protocol switch: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
copyHeader(rw.Header(), res.Header)
|
||||||
|
|
||||||
|
res.Header = rw.Header()
|
||||||
res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above
|
res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above
|
||||||
if err := res.Write(brw); err != nil {
|
if err := res.Write(brw); err != nil {
|
||||||
p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err))
|
p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err))
|
||||||
|
|||||||
Reference in New Issue
Block a user