ZeroNet Blogs

Static ZeroNet blogs mirror

Today I Learned

We constantly learn new things This is @ks' repo to share those learnings

[Python] Leap second poppycock

- Posted in Today I Learned by with comments

So, tonight we're supposed to insert an extra second 🡕 after 23:59:59 UTC, effectively giving us 23:59:60 before we reach midnight. It seems Python doesn't agree:

#!/usr/bin/python3

from datetime import (datetime, timedelta)
from pytz import UTC
from sys import stderr

try:
    leap = datetime(2016, 12, 31, 23, 59, 60, tzinfo=UTC)
except ValueError as error:
    print(str(error), file=stderr)
    leap = datetime(2016, 12, 31, 23, 59, 59, tzinfo=UTC)
    leap += timedelta(seconds=1)

print('{:%FT%T%z}'.format(leap))

# eof

Let's try:

$ python3 leapsectest.py
second must be in 0..59
2017-01-01T00:00:00+0000

Poppycock! 😒

Next time somebody tells you that everything in Python is an object, call bullshit:

>>> [m for m in dir(7) if not m.startswith('__')]
['bit_length',
 'conjugate',
 'denominator',
 'from_bytes',
 'imag',
 'numerator',
 'real',
 'to_bytes']
>>> 7.to_bytes(1, 'big')
  File "<stdin>", line 1
    7.to_bytes(1, 'big')
             ^
SyntaxError: invalid syntax
>>> i = 7
>>> i.to_bytes(1, 'big')
b'\x07'
>>> 

By default, systemd-networkd generates IPv6 addresses based on the interface's MAC address, which is undesirable. Here's how to have it generate dynamic addresses using SLAAC without disclosing MAC addresses.

To enable privacy extensions for all interfaces add the following to sysctl:

# /etc/sysctl.d/25-ipv6.conf
net.ipv6.conf.all.use_tempaddr=2
net.ipv6.conf.default.use_tempaddr=2

My Raspberry Pi 2 uses eth0 as its network interface and for some reason I need to explicitly mention eth0 in said conf:

net.ipv6.conf.eth0.use_tempaddr=2

Then instruct systemd-networkd to obey the kernel settings:

; /etc/systemd/network/enp3s0.network

[Match]
Name=enp3s0

[Network]
DHCP=yes

IPv6PrivacyExtensions=kernel

Back in March I couldn't seem to run Caddy 🡕 in front of Zeronet because of websocket troubles. Either Caddy has been improved since then or @keith­irwin found the solution. Either way, here's how:

zero.example.net {
  # Enable HSTS
  header / Strict-Transport-Security "max-age=31556926"
  tls {
    key_type p384
  }
  proxy /          <http://127.0.0.1:43110> {
    transparent
  }
  proxy /Websocket <http://127.0.0.1:43110> {
    websocket
  }
  # We don't want the world to access our private instance
  basicauth myUsername myPassword {
    /
  }
}

And contrary to the documentation, it is unnecessary to disable HTTP/2 (something that would sadly affect all domains served).

With this configuration Caddy will - obtain a certificate from Let's Encrypt 🡕 - serve all requests to zero.example.net over TLS

So now I can access my Zeronet from everywhere.

Caveat: Caddy doesn't seem to be quite stable here. Very often Caddy exits with this error:

Aug 31 10:15:06 home caddy[20251]: panic: not a Flusher
Aug 31 10:15:06 home caddy[20251]: goroutine 106 [running]:
Aug 31 10:15:06 home caddy[20251]: panic(0xcac000, 0xc420495e30)
Aug 31 10:15:06 home caddy[20251]:     /usr/local/go/src/runtime/panic.go:500 +0x1a1
Aug 31 10:15:06 home caddy[20251]: github.com/mholt/caddy/caddyhttp/httpserver.(*ResponseRecorder).Flush(0xc4205e54f0)
Aug 31 10:15:06 home caddy[20251]:     /tmp/custombuild_6580_159870072/src/github.com/mholt/caddy/caddyhttp/httpserver/recorder.go:87 +0xda
Aug 31 10:15:06 home caddy[20251]: github.com/mholt/caddy/caddyhttp/proxy.(*maxLatencyWriter).flushLoop(0xc420612540)
Aug 31 10:15:06 home caddy[20251]:     /tmp/custombuild_6580_159870072/src/github.com/mholt/caddy/caddyhttp/proxy/reverseproxy.go:378 +0x156
Aug 31 10:15:06 home caddy[20251]: created by github.com/mholt/caddy/caddyhttp/proxy.(*ReverseProxy).copyResponse
Aug 31 10:15:06 home caddy[20251]:     /tmp/custombuild_6580_159870072/src/github.com/mholt/caddy/caddyhttp/proxy/reverseproxy.go:247 +0x2e1

The bug has been reported as issue #1083 🡕.

Update: The solution is to not enable QUIC.

Plant nutrient deficiency chart (Found on Twitter with no reference to the source.)

Move from an A to an A+ server rating on SSL Labs:

example.com {
  header / "Strict-Transport-Security", "max-age=31556926; includeSubDomains"
    ⋮
}

For long-running domains you can add a preload to the stanza:

example.com {
  header / "Strict-Transport-Security", "max-age=31556926; includeSubDomains; preload"
    ⋮
}

Then add the domain to the HSTS preload list 🡕

See also

Looking for a good coding font? Cat this file in your terminal.

Easily confused glyphs

  • b69B8Ø0Oo
  • 1Il|
  • ij
  • 5S
  • 2Z
  • 9gq
  • co
  • rn m
  • cl d
  • vv w
  • .,
  • :;
  • `'
  • ''"
  • ' and ‘’ (curved/smart/curly single quotes)
  • " and “” (curved/smart/curly double quotes)
  • ~-
  • – — (n-dash, m-dash)
  • {[()]}
  • u and µ (mu)
  • v and ν (nu)

Uppercase vs. lowercase letters

  • Ww
  • Xx
  • Zz
  • Vv
  • Uu
  • Cc
  • Ss

External link(s)

[Python] Anaconda cleanup

- Posted in Today I Learned by with comments

$ conda clean -tp   # t = tarballs, p = unused packages

Cleaned out just short of 1 GB of disk space.

$ ssh-keygen -G moduli-2048.candidates -b 2048
$ ssh-keygen -T moduli-2048 -f moduli-2048.candidates

Then install the generated moduli-2048 file as /etc/ssh/moduli.

Update Generating and verifying 2048, 3072, …, 8192 bits moduli will take days (if not weeks).

2 Ton Digital runs a public DH parameter service 🡕 with a straight-forward API.

TLS Interposer 🡕 is not a new piece of software. However, I thought it would be interesting to learn about Zeronet's choice of TLS ciphers with and without TLS Interposer.

Without TLS Interposer

Grabbing data from the /Stats page I found that almost 9 out of 10 connections were using the ECDHE-RSA-AES128-GCM-SHA256 cipher suite that sports medium-high grade encryption and forward secrecy, while close to 1 out of 10 were using a cipher suite that doesn't support forward secrecy:

     91 ECDHE-RSA-AES128-GCM-SHA256
     12 AES128-GCM-SHA256
      1 AES256-SHA

With TLS Interposer

Next I installed the TLS Interposer library 🡕 and started Zeronet with a few simple requirements:

export LD_PRELOAD='/usr/local/lib/tlsinterposer.so'
export TLS_INTERPOSER_CIPHERS='kEECDH:kEDH:!aNULL:!eNULL:!EXPORT:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SSLv3:!TLSv1'
export TLS_INTERPOSER_OPTIONS='+sorder'
python2 zeronet.py

or, in common language: 1. Mandatory ephemeral key agreement (“kEECDH:kEDH”) 2. Use only high grade encryption (“!EXPORT:!MEDIUM:!LOW”) 3. Drop obsolete protocols (“!SSLv3:!TLSv1”) 4. Let me decide the cipher order (“+sorder”)

The results?

    128 ECDHE-RSA-AES256-GCM-SHA384
     12 tls-rsa

I frankly don't know what the tls-rsa thing stands for (if you do, please chime in below), but the rest of the connections have been upgraded so that all are using the ECDHE-RSA-AES256-GCM-SHA384 cipher suite, meaning AES256 encryption instead of AES128, and SHA384 hashing instead of SHA256, and of course forward secrecy.

The downside of all this is that if a peer doesn't support any of the protocols and ciphers you're offering, then no connection can be established.

With the restrictions I set on TLS_INTERPOSER_CIPHERS my Zeronet node now offers the following ciphers:

$ openssl ciphers -v "${TLS_INTERPOSER_CIPHERS}"
ECDHE-RSA-AES256-GCM-SHA384   TLSv1.2 Kx=ECDH Au=RSA   Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384       TLSv1.2 Kx=ECDH Au=RSA   Enc=AES(256)    Mac=SHA384
ECDHE-ECDSA-AES256-SHA384     TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256)    Mac=SHA384
ECDHE-RSA-AES128-GCM-SHA256   TLSv1.2 Kx=ECDH Au=RSA   Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
ECDHE-RSA-AES128-SHA256       TLSv1.2 Kx=ECDH Au=RSA   Enc=AES(128)    Mac=SHA256
ECDHE-ECDSA-AES128-SHA256     TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128)    Mac=SHA256
DHE-RSA-AES256-GCM-SHA384     TLSv1.2 Kx=DH   Au=RSA   Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-SHA256         TLSv1.2 Kx=DH   Au=RSA   Enc=AES(256)    Mac=SHA256
DHE-RSA-AES128-GCM-SHA256     TLSv1.2 Kx=DH   Au=RSA   Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES128-SHA256         TLSv1.2 Kx=DH   Au=RSA   Enc=AES(128)    Mac=SHA256
$ # “Kx” = key exchange, “Au” = authentication, “Enc” = encryption

Am I being too restrictive?

See also