GitLab is used only for code review, issue tracking and project management. Canonical locations for source code are still https://gitweb.torproject.org/ https://git.torproject.org/ and git-rw.torproject.org.

Use different end points for Web and API.

parent 3a201b1f
Bridgestrap Bridgestrap
=========== ===========
Bridgestrap implements a REST API (for machines) and a Web interface (for Bridgestrap implements a API (for machines) and a Web interface (for people) to
people) to test a given bridge line by spawning a tor instance and having it test a given bridge line by spawning a tor instance and having it bootstrap
bootstrap over the bridge line. over the bridge line.
Installation Installation
------------ ------------
...@@ -24,21 +24,25 @@ the address and port that bridgestrap is listening on. Use the argument ...@@ -24,21 +24,25 @@ the address and port that bridgestrap is listening on. Use the argument
Input Input
----- -----
Clients send bridge lines (in this case `STRING`) to a REST API, using an HTTP Clients send bridge lines to the following API, using an HTTP GET request, and
GET request: 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 The request body must look as follows:
"Bridge" prefix) that tor accepts. Here are a few examples:
* `1.2.3.4%3A1234` {"bridge_line": "BRIDGE_LINE"}
* `1.2.3.4%3A1234%201234567890ABCDEF1234567890ABCDEF12345678`
* `obfs4%201.2.3.4%3A1234%20cert%3DfJRlJc0T7i2Qkw3SyLQq%2BM6iTGs9ghLHK65LBy%2FMQewXJpNOKFq63Om1JHVkLlrmEBbX1w%20iat-mode%3D0`
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 Output
------ ------
......
...@@ -23,6 +23,10 @@ type TestResult struct { ...@@ -23,6 +23,10 @@ type TestResult struct {
Time float64 `json:"time"` 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 // limiter implements a rate limiter. We allow 1 request per second on average
// with bursts of up to 5 requests per second. // with bursts of up to 5 requests per second.
var limiter = rate.NewLimiter(1, 5) var limiter = rate.NewLimiter(1, 5)
...@@ -91,35 +95,48 @@ func createJsonResult(err error, start time.Time) string { ...@@ -91,35 +95,48 @@ func createJsonResult(err error, start time.Time) string {
func BridgeState(w http.ResponseWriter, r *http.Request) { func BridgeState(w http.ResponseWriter, r *http.Request) {
start := time.Now() start := time.Now()
r.ParseForm()
isWebRequest := r.Form.Get("web_request") != "" b, err := ioutil.ReadAll(r.Body)
if isWebRequest { defer r.Body.Close()
// Rate-limit Web requests to prevent someone from abusing this service if err != nil {
// as a port scanner. log.Printf("Failed to read HTTP body: %s", err)
if limiter.Allow() == false { http.Error(w, err.Error(), http.StatusInternalServerError)
SendHtmlResponse(w, "Rate limit exceeded.") return
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") bridgeLine := r.Form.Get("bridge_line")
if bridgeLine == "" { if bridgeLine == "" {
if isWebRequest { SendHtmlResponse(w, "No bridge line given.")
SendHtmlResponse(w, "No bridge line given.")
} else {
SendJSONResponse(w, createJsonResult(fmt.Errorf("No bridge line given"), start))
}
return return
} }
if err := bootstrapTorOverBridge(bridgeLine); err == nil {
err := bootstrapTorOverBridge(bridgeLine) SendHtmlResponse(w, SuccessPage)
if isWebRequest {
if err := bootstrapTorOverBridge(bridgeLine); err == nil {
SendHtmlResponse(w, SuccessPage)
} else {
SendHtmlResponse(w, FailurePage)
}
} else { } else {
SendJSONResponse(w, createJsonResult(err, start)) SendHtmlResponse(w, FailurePage)
} }
} }
...@@ -30,6 +30,12 @@ var routes = Routes{ ...@@ -30,6 +30,12 @@ var routes = Routes{
"/bridge-state", "/bridge-state",
BridgeState, BridgeState,
}, },
Route{
"BridgeStateWeb",
"GET",
"/result",
BridgeStateWeb,
},
} }
// Logger logs when we receive requests, and the execution time of handling // Logger logs when we receive requests, and the execution time of handling
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</header> </header>
<section id="content"> <section id="content">
<form method="GET" action="bridge-state"> <form method="GET" action="result">
<h1>Test your Tor bridge</h1> <h1>Test your Tor bridge</h1>
<p>Are you wondering if your new Tor bridge works? You have come to the <p>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&mdash;be it right place! This service lets you test any kind of bridge&mdash;be it
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment