Giter VIP home page Giter VIP logo

letsdane's People

Contributors

anunayj avatar buffrr avatar rafork avatar yagikota avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

letsdane's Issues

Require strong TLS 1.2 cipher suites for DANE secured connections

We can afford to be more picky about TLS cipher suites for DANE secured connections. Go's TLS stack is for the most part on par with web browsers but we can be even more picky than web browsers and reject some weak legacy ciphers.

I was thinking of bumping min TLS version to 1.3 but this may be too aggressive since some linux distros may still use older versions of openssl/nginx. Although, sites using fancy technologies like DANE today should probably be using TLS 1.3.

For now allowing only these cipher suites for TLS 1.2 seems appropriate (as of Go 1.17 I don't think the order is important):

CipherSuites: []uint16{
	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
	tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
	tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
	tls.TLS_AES_128_GCM_SHA256,
	tls.TLS_AES_256_GCM_SHA384,
	tls.TLS_CHACHA20_POLY1305_SHA256,
}

Subdomains

Do subdomains work?

I got this error from https://pinheadmz.proofofconcept.

Websites prove their identity via certificates. Firefox does not trust this site because it uses a certificate that is not valid for pinheadmz.proofofconcept.. The certificate is only valid for the following names: proofofconcept, *.proofofconcept, 142.93.115.133

Error code: MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

... but the TLD-only URL worked fine: https://proofofconcept/

Could be my certificate parameters but I was hoping *.proofofconcept would work.

Discord doesn't connect even with -skip-icann

I use letsdane on android (well, the proxy runs on a raspi). All apps and browsers work fine. DANE for Handshake names also works. But the Discord app doesn't. It's always on connecting. Could be a websocket thing or some kind of pinning, but I thought -skip-icann doesn't modify anything.

Will try to debug this more, just wanted to post it here first if you had any ideas.

Use latest Go version

Hi @buffrr
Thanks for awesome library!

If we are going to continue to develop this library, we'll have to increase Go version at some point.
Do you have plan to use latest Go version 1.21.

README suggestion

Hi, This isn't an issue, just a suggestion for your README. And a shameless plug.

I expect most website admins wouldn't know how to implement DANE for their websites. It's usually only of interest to mail admins. And the learning curve is a big thing. And the payoff (for website admins) is tiny, so there's not a lot of incentive.

I've just published https://github.com/raforg/danectl which makes it super easy to use certbot to create a current + next pair of certificates, configure and generate all the TLSA 3 1 1 records you need (mail/web/whatever) for you to publish to the DNS, check that they are published, and perform rollovers.

It makes implementing DANE so easy that it might be enough to convince website admins to give it a go. Especially if they're already using certbot.

Of course, DNSSEC has to come first, but apparently 20% of new .com domains have DNSSEC, and with bind-9.16+ (like on the new stable debian-11), it has finally become incredibly easy to implement DNSSEC (only one extra line of config!).

But feel free to ignore this.

Code to improve

After performing static analysis using golangci-lint, there are some code to improve.
Fixing these will make letsdane a better library.

golangci-lint run ./...
proxy/conn.go:48:10: Error return value of `io.Copy` is not checked (errcheck)
		io.Copy(src, dst)
		       ^
proxy/conn_test.go:22:19: Error return value of `client.Handshake` is not checked (errcheck)
		client.Handshake()
		                ^
proxy/conn_test.go:40:14: Error return value of `(*crypto/tls.Conn).Handshake` is not checked (errcheck)
	}).Handshake()
	            ^
proxy/proxy_test.go:18:10: Error return value of `w.Write` is not checked (errcheck)
		w.Write([]byte("hey"))
		       ^
proxy/proxy_test.go:76:19: Error return value of `clientConn.Write` is not checked (errcheck)
		clientConn.Write([]byte("bar"))
		                ^
proxy/proxy_test.go:110:11: Error return value of `w.Write` is not checked (errcheck)
			w.Write([]byte("hello"))
			       ^
dialer_test.go:16:11: Error return value of `wr.Write` is not checked (errcheck)
		wr.Write([]byte("foo"))
		        ^
dialer_test.go:38:12: Error return value of `conn.Write` is not checked (errcheck)
	conn.Write([]byte("GET / HTTP/1.1\nHost:example.org\n\r\n\r"))
	          ^
tls.go:71:18: Error return value of `conn.SetDeadline` is not checked (errcheck)
	conn.SetDeadline(time.Now().Add(time.Second * 3))
	                ^
tls.go:81:21: Error return value of `clientTLS.Handshake` is not checked (errcheck)
	clientTLS.Handshake()
	                   ^
tunnel.go:250:10: Error return value of `io.Copy` is not checked (errcheck)
		io.Copy(src, dst)
		       ^
tunnel_test.go:43:10: Error return value of `w.Write` is not checked (errcheck)
		w.Write([]byte("foo"))
		       ^
tunnel_test.go:104:14: Error return value of `conn.Write` is not checked (errcheck)
			conn.Write([]byte(fmt.Sprintf("GET %s HTTP/1.1\nHost:%s\nConnection:close\n\r\n\r", test.uri, test.host)))
			          ^
tunnel_test.go:132:11: Error return value of `wr.Write` is not checked (errcheck)
		wr.Write([]byte("foo"))
		        ^
tunnel_test.go:141:14: Error return value of `conn.Write` is not checked (errcheck)
			conn.Write([]byte("ALPN TEST"))
			          ^
cmd/letsdane/main.go:86:14: Error return value of `pem.Encode` is not checked (errcheck)
			pem.Encode(certOut, &pem.Block{
			          ^
cmd/letsdane/main.go:92:14: Error return value of `pem.Encode` is not checked (errcheck)
			pem.Encode(privOut, &pem.Block{
			          ^
cmd/letsdane/main.go:103:14: Error return value of `kOut.Write` is not checked (errcheck)
			kOut.Write(privOut.Bytes())
			          ^
resolver/resolver_test.go:403:6: func `rrsEq` is unused (unused)
func rrsEq(slice1, slice2 []dns.RR) bool {
     ^
cert.go:34:2: field `getCertificate` is unused (unused)
	getCertificate func(*tls.ClientHelloInfo) (*tls.Certificate, error)
	^
resolver/resolver_test.go:361:10: S1034: assigning the result of this type assertion to a variable (switch rr := rr.(type)) could eliminate type assertions in switch cases (gosimple)
		switch rr.(type) {
		       ^
resolver/resolver_test.go:363:18: S1034(related information): could eliminate this type assertion (gosimple)
			f = append(f, rr.(*dns.TLSA))
			              ^
resolver/stub_test.go:82:5: testinggoroutine: call to (*T).Fatal from a non-test goroutine (govet)
				t.Fatal(err)
				^
resolver/stub_test.go:87:5: testinggoroutine: call to (*T).Fatal from a non-test goroutine (govet)
				t.Fatal("dnssec-failed.org returned a valid response")
				^
resolver/stub_test.go:92:5: testinggoroutine: call to (*T).Fatal from a non-test goroutine (govet)
				t.Fatal(err)
				^
resolver/stub_test.go:96:5: testinggoroutine: call to (*T).Fatalf from a non-test goroutine (govet)
				t.Fatalf("got no ips")
				^
resolver/stub_test.go:105:5: testinggoroutine: call to (*T).Fatalf from a non-test goroutine (govet)
				t.Fatalf("got no tlsa records from freebsd.org")
				^
tunnel_test.go:373:10: ineffectual assignment to err (ineffassign)
			body, err := io.ReadAll(resp.Body)
			      ^
cert_test.go:89:2: SA4006: this value of `tlsc` is never used (staticcheck)
	tlsc, err = conf.GetCertificate(clientHello)
	^
cert_test.go:96:2: SA4006: this value of `tlsc` is never used (staticcheck)
	tlsc, err = conf.GetCertificate(clientHello)
	^
cmd/letsdane/main.go:124:5: SA1019: x509.IsEncryptedPEMBlock has been deprecated since Go 1.16 because it shouldn't be used: Legacy PEM encryption as specified in RFC 1423 is insecure by design. Since it does not authenticate the ciphertext, it is vulnerable to padding oracle attacks that can let an attacker recover the plaintext. (staticcheck)
	if x509.IsEncryptedPEMBlock(block) {
	   ^
cmd/letsdane/main.go:129:25: SA1019: x509.DecryptPEMBlock has been deprecated since Go 1.16 because it shouldn't be used: Legacy PEM encryption as specified in RFC 1423 is insecure by design. Since it does not authenticate the ciphertext, it is vulnerable to padding oracle attacks that can let an attacker recover the plaintext. (staticcheck)
		decryptedBlock, err = x509.DecryptPEMBlock(block, []byte(*pass))
		                      ^
resolver/stub_test.go:77:3: SA2002: the goroutine calls T.Fatal, which must be called in the same goroutine as the test (staticcheck)
		go func(proto string) {
		^

DoT Support

Is their a way to use a DoT server with LetsDANE?

Verifying VPN Servers using LetsDANE

I've been experimenting with using the LetsDANE http proxy to connect to a VPN server, but I end up running into errors when trying to validate SSL. (Both with and without a reverse proxy)

The only noticeable error I received was this:

C0CC8B6670000000:error:0A000126:SSL routines:ssl3_read_n:unexpected eof while reading:ssl/record/rec_layer_s3.c:321:

This is the error that occurred without using reverse proxy - The VPN server has the cert set directly through the VPN software, and then I specified the IP address of the VPN server in the DNS for the Handshake domain.

Build Failure in *BSD

The below is an effort to build letsdane in FreeBSD.

letsdane/cmd/letsdane # go build -tags unbound

github.com/miekg/unbound

/go/pkg/mod/github.com/miekg/[email protected]/unbound.go:36:10: fatal error: 'unbound.h' file not found
#include <unbound.h>
^~~~~~~~~~~
1 error generated.
/letsdane/cmd/letsdane # locate unbound.
/usr/local/lib/libunbound.a
/usr/local/include/unbound.h
/usr/local/lib/libunbound.so
......
......
......

Any suggestions on how to point at the location of the unbound.h? Thanks for your prompt response to the "IP_Addr:Port" issue. If you would want to include it in the README in addition to the "-r" and referral to the help, that would be clearer.

Skip result of TLSA lookups for bad nameservers

Some nameservers timeout or return SERVFAIL for any record type they don't understand

An example of such a server found in the wild (at the time of writing)

dig @dns1.tribpub.com _443._tcp.www.chicagotribune.com tlsa

This nameserver doesn't even understand DNSSEC, but a recursive DNSSEC resolver will return SERVFAIL in this case which is not an acceptable answer for DANE and the website breaks.

A DANE client should not expect that all nameservers will answer reliably for the TLSA record type.

To avoid breaking services that use such nameservers, we should:

  • Determine if either A or AAAA records of the host are in a DNSSEC-signed zone
  • If the zone is unsigned, it's safe to skip result of the TLSA lookup without risking a downgrade attack.

Credits to @vdukhovni for telling me about this idea

Proposal: Set listening IP_Addr and Port

The following is your instruction to run Letsdane:

./letsdane

Add Let's DANE proxy to your web browser 127.0.0.1:8080

T
If you could you make it possible to set the IP_Addr and Port as (additional) arguments at which the service runs, that would be lovely.

Thank you for this interesting project.

Add DANE-TA(2) support

While PKIX certificate usages are optional, for complete DANE implementation we should support DANE-TA(2). This is useful if server administrators that would like to pin self-signed CA instead of pinning an individual end entity certificate for each service.

From RFC7671

Some domains may prefer to avoid the operational complexity of
publishing unique TLSA RRs for each TLS service. If the domain
employs a common issuing CA to create certificates for multiple TLS
services, it may be simpler to publish the issuing authority as a TA
for the certificate chains of all relevant services. The TLSA query
domain (TLSA base domain with port and protocol prefix labels) for
each service issued by the same TA may then be set to a CNAME alias
that points to a common TLSA RRset that matches the TA

Timeouts

Roughly 1 in 3 requests I make through this result in a long pause and then a timeout error. The interesting thing I've found is that while letsdane isn't responding I'm able to get rpc responses from hsd so it doesn't seem like an issue with hsd.

Trojan:Win32/Bearfoos.A!ml

all the sudden , app crashed and now is impossible to start service, unless i hit allow , why now after all this time?

Building Static Binaries for multi platform deployment.

Static Binaries for each platform can be built using:

Linux

Static Binaries for Linux can be made using the following Dockerfile (or running the commands in Dockerfile manually).

# DOCKER_BUILDKIT=1 docker build -f static.Dockerfile -o build/ . 
FROM golang:alpine AS base
RUN apk update && apk add linux-headers gcc make perl musl-dev expat-dev openssl-libs-static openssl-dev


#Install Unbound
FROM base as setup-unbound
WORKDIR /tmp
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-1.13.1.tar.gz && tar -xzf unbound-1.13.1.tar.gz
WORKDIR /tmp/unbound-1.13.1
RUN ./configure --prefix=/opt/install
RUN make && make install

FROM base as builder
#Install Dependencies
COPY --from=setup-unbound /opt/install/ /usr/local
#Optionally export this layer and cache this permanently somewhere.

#Copy stuff overgo mod download
WORKDIR /tmp/dane
COPY go.mod /tmp/dane/go.mod
RUN go mod download
#Will allow caching dependencies in layers.

COPY . /tmp/dane/
WORKDIR /tmp/dane/cmd/letsdane
#Build Static
RUN go build -tags unbound --ldflags '-extldflags "-lunbound -lssl -lcrypto -static"'

FROM scratch
COPY --from=builder /tmp/dane/cmd/letsdane/letsdane /
ENTRYPOINT [ "letsdane" ]

Use DOCKER_BUILDKIT=1 docker build -f static.Dockerfile -o build/ . to export the binary into build directory.

Running this first time can take >500 seconds (Mostly because of all the compiling that needs to be done for unbound and openssl), The Image layer can be exported to Dockerhub and used repeatedly if necessary. Subsequent builds should take <100 seconds.

Todo:

  • Document building static binaries for Linux
  • Document building static binaries for Windows
  • Document building static binaries for MacOS

DoH/DoT certificate pinning

One issue with allowing users to trust a validating resolver over a secure channel is that the secure connection itself relies on WebPKI which takes away the advantages provided by DANE.

Pinning is typically not recommended by DoH providers as the public key of the certificate could change, which will eventually break clients' setup. Even though trusting a resolver to do the validation is not ideal or recommended it's still needed by some users that don't want to compile letsdane with unbound and don't have a validating resolver.

Maybe with DANE-TA(2) support (issue #10) we can allow pinning the CA of a DoH or DoT provider? The CA is less likely to change making the setup less brittle. The advantage of this is trusting a single CA used by the resolver instead of all CAs installed on the device.

Users still need to manually provide a TLSA record for the pinning (which can be optional)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.