From 0b06c612a1734d72c4a2e83a64ca90bc05a7d422 Mon Sep 17 00:00:00 2001 From: Philipp Winter Date: Tue, 18 Aug 2020 09:02:22 -0700 Subject: [PATCH] Use different end points for Web and API. --- README.md | 30 ++++++++++++--------- handlers.go | 63 ++++++++++++++++++++++++++++---------------- main.go | 6 +++++ templates/index.html | 2 +- 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 548e1ee..9a8a32d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ Bridgestrap =========== -Bridgestrap implements a REST API (for machines) and a Web interface (for -people) to test a given bridge line by spawning a tor instance and having it -bootstrap over the bridge line. +Bridgestrap implements a API (for machines) and a Web interface (for people) to +test a given bridge line by spawning a tor instance and having it bootstrap +over the bridge line. Installation ------------ @@ -24,21 +24,25 @@ the address and port that bridgestrap is listening on. Use the argument Input ----- -Clients send bridge lines (in this case `STRING`) to a REST API, using an HTTP -GET request: +Clients send bridge lines to the following API, using an HTTP GET request, and +place the bridge line in the request body: - https://HOST/bridge-state?bridge_line=STRING + https://HOST/bridge-state -The value of `bridge_line` can be any URL-encoded bridge line (excluding the -"Bridge" prefix) that tor accepts. Here are a few examples: +The request body must look as follows: -* `1.2.3.4%3A1234` -* `1.2.3.4%3A1234%201234567890ABCDEF1234567890ABCDEF12345678` -* `obfs4%201.2.3.4%3A1234%20cert%3DfJRlJc0T7i2Qkw3SyLQq%2BM6iTGs9ghLHK65LBy%2FMQewXJpNOKFq63Om1JHVkLlrmEBbX1w%20iat-mode%3D0` + {"bridge_line": "BRIDGE_LINE"} -You can test bridgestrap's API as follows: +The value of "bridge_line" can be any bridge line (excluding the "Bridge" +prefix) that tor accepts. Here are a few examples: - curl "localhost:5000/bridge-state?bridge_line=1.2.3.4%3A1234" +* `1.2.3.4:1234` +* `1.2.3.4:1234 1234567890ABCDEF1234567890ABCDEF12345678` +* `obfs4 1.2.3.4:1234 cert=fJRlJc0T7i2Qkw3SyLQq+M6iTGs9ghLHK65LBy/MQewXJpNOKFq63Om1JHVkLlrmEBbX1w iat-mode=0` + +You can test bridgestrap's API over the command line as follows: + + curl -X GET localhost:5000/bridge-state -d '{"bridge_line": "BRIDGE_LINE"}' Output ------ diff --git a/handlers.go b/handlers.go index e86c604..f6f8eb8 100644 --- a/handlers.go +++ b/handlers.go @@ -23,6 +23,10 @@ type TestResult struct { Time float64 `json:"time"` } +type TestRequest struct { + BridgeLine string `json:"bridge_line"` +} + // limiter implements a rate limiter. We allow 1 request per second on average // with bursts of up to 5 requests per second. var limiter = rate.NewLimiter(1, 5) @@ -91,35 +95,48 @@ func createJsonResult(err error, start time.Time) string { func BridgeState(w http.ResponseWriter, r *http.Request) { start := time.Now() - r.ParseForm() - isWebRequest := r.Form.Get("web_request") != "" - if isWebRequest { - // Rate-limit Web requests to prevent someone from abusing this service - // as a port scanner. - if limiter.Allow() == false { - SendHtmlResponse(w, "Rate limit exceeded.") - return - } + + b, err := ioutil.ReadAll(r.Body) + defer r.Body.Close() + if err != nil { + log.Printf("Failed to read HTTP body: %s", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + req := &TestRequest{} + if err := json.Unmarshal(b, &req); err != nil { + log.Printf("Failed to unmarshal HTTP body %q: %s", b, err) + http.Error(w, err.Error(), http.StatusBadRequest) + return } + if req.BridgeLine == "" { + log.Printf("Got request with empty bridge line.") + http.Error(w, "no bridge line given", http.StatusBadRequest) + return + } + err = bootstrapTorOverBridge(req.BridgeLine) + SendJSONResponse(w, createJsonResult(err, start)) +} + +func BridgeStateWeb(w http.ResponseWriter, r *http.Request) { + + r.ParseForm() + // Rate-limit Web requests to prevent someone from abusing this service + // as a port scanner. + if limiter.Allow() == false { + SendHtmlResponse(w, "Rate limit exceeded.") + return + } bridgeLine := r.Form.Get("bridge_line") if bridgeLine == "" { - if isWebRequest { - SendHtmlResponse(w, "No bridge line given.") - } else { - SendJSONResponse(w, createJsonResult(fmt.Errorf("No bridge line given"), start)) - } + SendHtmlResponse(w, "No bridge line given.") return } - - err := bootstrapTorOverBridge(bridgeLine) - if isWebRequest { - if err := bootstrapTorOverBridge(bridgeLine); err == nil { - SendHtmlResponse(w, SuccessPage) - } else { - SendHtmlResponse(w, FailurePage) - } + if err := bootstrapTorOverBridge(bridgeLine); err == nil { + SendHtmlResponse(w, SuccessPage) } else { - SendJSONResponse(w, createJsonResult(err, start)) + SendHtmlResponse(w, FailurePage) } } diff --git a/main.go b/main.go index a6f139b..62225cc 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,12 @@ var routes = Routes{ "/bridge-state", BridgeState, }, + Route{ + "BridgeStateWeb", + "GET", + "/result", + BridgeStateWeb, + }, } // Logger logs when we receive requests, and the execution time of handling diff --git a/templates/index.html b/templates/index.html index 7103050..498a57d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -16,7 +16,7 @@
-
+

Test your Tor bridge

Are you wondering if your new Tor bridge works? You have come to the right place! This service lets you test any kind of bridge—be it -- GitLab