Skip to content

Commit d8d6190

Browse files
authored
Merge pull request #65 from skatsubo/chore/typos
Fix typos in text and comments and in http resp handling in code
2 parents e73fe59 + 16e5dd5 commit d8d6190

File tree

5 files changed

+14
-14
lines changed

5 files changed

+14
-14
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0
5555
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
5656
```
5757

58-
What this does is disable a [recent kernel feature that restricts unpriveleged user namespaces](https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces). The above may also be needed on other distros that have disabled unpriveleged user namespaces by default. I will update this documentation as I learn more. I am investigating ways to avoid the need for this entirely by shipping an apparmor profile with httptap.
58+
What this does is disable a [recent kernel feature that restricts unprivileged user namespaces](https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces). The above may also be needed on other distros that have disabled unprivileged user namespaces by default. I will update this documentation as I learn more. I am investigating ways to avoid the need for this entirely by shipping an apparmor profile with httptap.
5959

6060
# Quickstart
6161

@@ -120,7 +120,7 @@ $ httptap --https 443 6443 -- kubectl get all --insecure-skip-tls-verify
120120
<ordinary kubectl output here>
121121
```
122122

123-
In the above, `--insecure-skip-tls-verify` is necessary because kubectl doesn't use the httptap-generated certificate authority, and `--https 443 6443` says to treat TCP connections on ports 443 and 6443 as HTTPS connections, which is needed because my cluter's API endpoint uses port 6443.
123+
In the above, `--insecure-skip-tls-verify` is necessary because kubectl doesn't use the httptap-generated certificate authority, and `--https 443 6443` says to treat TCP connections on ports 443 and 6443 as HTTPS connections, which is needed because my cluster's API endpoint uses port 6443.
124124

125125
Let's see how DNS-over-HTTP works when you use `--doh-url` with curl:
126126

@@ -174,11 +174,11 @@ There are many HAR viewers out there that can visualize this dump file. For exam
174174

175175
![HAR Analyzer Screenshot](docs/har-screenshot.png)
176176

177-
Again, what you're looking at here is one HTTP request to https://monasticacademy.org that returns a 308 Redirect, followed by a second HTTP request to https://www.monasticacademy.org that return a 200 OK.
177+
Again, what you're looking at here is one HTTP request to https://monasticacademy.org that returns a 308 Redirect, followed by a second HTTP request to https://www.monasticacademy.org that returns a 200 OK.
178178

179179
# Reaching localhost
180180

181-
To reach a localhost port, replace "localhost" with "host.httptap.local" or the special IP address 169.254.77.65. Traffic to these destinations will routed to localhost on your machine.
181+
To reach a localhost port, replace "localhost" with "host.httptap.local" or the special IP address 169.254.77.65. Traffic to these destinations will be routed to localhost on your machine.
182182

183183
The situation here is that in linux every network namespace automatically gets its own loopback device (127.0.0.1), and these can't be shared. This means that if a process running within httptap tries to connect to 127.0.0.1:1234, it'll actually be connecting to a "different" 127.0.0.1 from another process on your machine listening on this same address and port, and you won't be able to connect.
184184

@@ -197,7 +197,7 @@ $ httptap --no-exit -- code --ignore-certificate-errors .
197197
...
198198
```
199199

200-
You will have to press ctrl+C to kill httptap once you exit vscode.
200+
You will have to press Ctrl+C to kill httptap once you exit vscode.
201201

202202
In the above, without `--no-exit`, httptap would exit immediately after launching vscode. However, even though the subprocess launched by httptap has exited, that subprocess created a whole separate process tree before it did so. That process tree is the actual GUI app, and it is still pinned to the httptap network namespace. If httptap exits then the network namespace will continue to exist, and the GUI app will continue to run, but nobody will be reading packets sent to the TUN device that is only available network interface in that network namespace, and as a result the app will have no network connectivity. The workaround for this is the `--no-exit` flag that asks httptap to keep proxying network traffic even after the immediate subprocess exits.
203203

@@ -241,15 +241,15 @@ When you run `httptap -- <command>`, httptap runs `<command>` in an isolated net
241241

242242
In linux, there is a kernel API for creating and configuring network interfaces. Conventionally, a network interface would be a physical ethernet or WiFi controller in your computer, but it is possible to create a special kind of network interface called a TUN device. A TUN device shows up to the system in the way that any network interface shows up, but any traffic written to it will be delivered to a file descriptor held by the process that created it. Httptap creates a TUN device and runs the subprocess in an environment in which all network traffic is routed through that device.
243243

244-
There is also a kernel API in linux for creating network namespaces. A network namespace is a list of network interfaces and routing rules. When a process is started in linux, it can be run in a specified network namespace. By default, processes run in a root network namespace that we do not want to make chagnes to because doing so would affect all network traffic on the system. Instead, we create a network namespace in which there are only two network interfaces: a loopback device (127.0.0.1) and a TUN device that delivers traffic to us. Then we run the subprocess in that namespace.
244+
There is also a kernel API in linux for creating network namespaces. A network namespace is a list of network interfaces and routing rules. When a process is started in linux, it can be run in a specified network namespace. By default, processes run in a root network namespace that we do not want to make changes to because doing so would affect all network traffic on the system. Instead, we create a network namespace in which there are only two network interfaces: a loopback device (127.0.0.1) and a TUN device that delivers traffic to us. Then we run the subprocess in that namespace.
245245

246246
The traffic from the network device is delivered to us as raw IP packets. We must parse the IP packets as well as the inner TCP and UDP packets, and write raw IP packets back to the subprocess. This requires a software implementation of the TCP/IP protocol, which is by far the most difficult part of httptap. The TCP/IP implementation in httptap is missing many aspects of the full TCP protocol, but still works reasonably well for its purpose.
247247

248248
Suppose the subprocess makes an HTTP request to www.example.com. The first thing we receive is a TCP SYN packet addressed to 93.184.215.14 (the current IP address of example.com). We respond with a SYN+ACK packet with source address 93.184.215.14, though in truth the packet did not come from 93.184.215.14, but from us. Separately, we establish our own TCP connection to 93.184.215.14 using the ordinary sockets API in the linux kernel. When the subprocess sends data to 93.184.215.14 we relay it over our separate TCP connection, and vice versa for return data. This is a traditional transparent TCP proxy, and in this way we can view all data flowing to and from the subprocess, though we won't be able to decrypt HTTPS traffic without a bit more work.
249249

250250
When a client makes an HTTPS request, it asks the server for evidence that it is who it says it is. If the server has a certificate signed by a certificate authority, it can use that certificate to prove that it is who it says it is. The client will only accept such a certificate if it trusts the certificate authority that signed the certificate. Operating systems, web browsers, and many other pieces of software come with a list of a few hundred certificate authorities that they trust. Many of these pieces of software have ways for users to add additional certificate authorities to this list. We make use of this.
251251

252-
When httptap starts, it creates a certificate authority (actually a private key plus a corresponding x509 certificate), writes it to a file on the filesystem visible only to the subprocess, and sets a few environment variables -- again only visible to the subprocess being run -- that add this certificate authority to the list of trusted certificate authorities. Since the subprocess trusts this certificate authority, and httptap holds the private key for the certificate authority, it can prove to the subprocess that it is the server which which the subprocess was trying to communicate. In this way we can read the plaintext HTTP requests.
252+
When httptap starts, it creates a certificate authority (actually a private key plus a corresponding x509 certificate), writes it to a file on the filesystem visible only to the subprocess, and sets a few environment variables -- again only visible to the subprocess being run -- that add this certificate authority to the list of trusted certificate authorities. Since the subprocess trusts this certificate authority, and httptap holds the private key for the certificate authority, it can prove to the subprocess that it is the server which the subprocess was trying to communicate. In this way we can read the plaintext HTTP requests.
253253

254254
# How it was made
255255

dns.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (p dnsPairA) Answers() []string {
4545
return answers
4646
}
4747

48-
// dnsWatcher receives information about each intercepted DNS query, and the response provided
48+
// dnsWatcher receives information about each intercepted DNS query and the response provided
4949
type dnsWatcher func(*dnsCall)
5050

5151
// the listeners waiting for HTTPCalls

http.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ var httpListeners []httpListener
4949
// the complete set of HTTP calls up to the present moment
5050
var httpCalls []*HTTPCall
5151

52-
// the mutex that protects the above slcies
52+
// the mutex that protects the above slices
5353
var httpMu sync.Mutex
5454

5555
// add a listener that will receive events for each next HTTP call; the set of historical
@@ -276,7 +276,7 @@ func proxyHTTPScheme(dst http.RoundTripper, conn net.Conn, outgoingScheme string
276276
responsebody, err := decodeContent(&respbody, resp.Header["Content-Encoding"])
277277
if err != nil {
278278
errorf("error decoding response body as %v, will return raw bytes", resp.Header["Content-Encoding"])
279-
requestbody = reqbody.Bytes()
279+
responsebody = respbody.Bytes()
280280
}
281281

282282
// make the summary the we will log to disk and expose via the API

httptap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ func Main() error {
764764
return fmt.Errorf("invalid stack %q; valid choices are 'gvisor' or 'homegrown'", args.Stack)
765765
}
766766

767-
verbosef("launching third stage targetting uid %d, gid %d...", args.UID, args.GID)
767+
verbosef("launching third stage targeting uid %d, gid %d...", args.UID, args.GID)
768768

769769
// launch the third stage in a second user namespace, this time with mappings reversed
770770
cmd := exec.Command("/proc/self/exe")

tcp.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ func (s *tcpStream) Write(payload []byte) (int, error) {
287287
SrcPort: layers.TCPPort(s.world.Port),
288288
DstPort: layers.TCPPort(s.subprocess.Port),
289289
Seq: atomic.AddUint32(&s.seq, sz) - sz, // sequence number on our side
290-
Ack: atomic.LoadUint32(&s.ack), // laste sequence number we saw on their side
290+
Ack: atomic.LoadUint32(&s.ack), // last sequence number we saw on their side
291291
ACK: true, // this indicates that we are acknolwedging some bytes
292292
Window: 64240, // number of bytes we are willing to receive (copied from sender)
293293
}
@@ -333,10 +333,10 @@ func (s *tcpStream) Write(payload []byte) (int, error) {
333333
func (s *tcpStream) Close() error {
334334
switch s.state {
335335
case StateInit:
336-
errorf("application tried tp close a TCP stream in state %v, returning error", s.state)
336+
errorf("application tried to close a TCP stream in state %v, returning error", s.state)
337337
return fmt.Errorf("cannot close TCP stream in state %v", s.state)
338338
case StateFinished:
339-
verbosef("application tried tp close a TCP stream in state %v, ignoring", s.state)
339+
verbosef("application tried to close a TCP stream in state %v, ignoring", s.state)
340340
return nil
341341
}
342342

0 commit comments

Comments
 (0)