CSS for viewing plain text email with fixed width font after gmail 2018 Q3 update

.a3s, .g6 {
	font-family: monospace !important;

Use something simple like Chrome Resource Override extension should just work. Set Tab URL to


and inject css to body.

As to composing emails, you may try this:

.editable {
	font-family: monospace !important;
	max-width: 78ch;
	word-wrap: break-word;

DD-WRT and HiNet dynamic IPv6 service

Based on Buffalo WZR-HP-G450H model, with firmware version: DD-WRT v3.0-r30357 std (12/20/17) from Buffalo.

HiNet service is PPPoE dynamic IPv4 and IPv6.

It’s quite simple at first place.

  1. Enable IPv6 support under Setup -> IPv6.
  2. Type is DHCPv6 with Prefix Delegation.
  3. The prefix is 64.
  4. Enable radvd.
  5. Enable custom radvd config too. Differences between auto-generated radvd config are auto prefix (::/64) and turn on DeprecatePrefix option.
interface br0
 IgnoreIfMissing on;
 AdvSendAdvert on;
 MinRtrAdvInterval 3;
 MaxRtrAdvInterval 10;
 AdvHomeAgentFlag off;
 AdvManagedFlag off;
 AdvOtherConfigFlag on;
 AdvLinkMTU 1492;
 prefix ::/64
  AdvOnLink on;
  AdvAutonomous on;
  DeprecatePrefix on;
 RDNSS 2001:b000:168::1 2001:b000:168::2 {};

So far so good, until HiNet drops your PPPoE connection then gives you a new IPv4 address and IPv6 prefix. Here is a simple workaround to deal with it, but you need to enable USB support and put a custom shell script in it.

I use an old 4G usb thumb drive, and format it to 3 partitions before plugging in the device. First partition is 512M swap, second is 3G ext2 for /opt, rest space is ext2 also, for /jffs.

On DD-WRT web interface, under Services -> USB, enable Core USB Support, USB Storage Support, and fill UUIDs for /opt and /jffs accordingly.

When all stuff ready, put a custom script: /jffs/etc/config/radvd.wanup

#LOGFILE can be anywhere in your /opt or /jffs.
PPP0=`ifconfig ppp0`
UPTIME=`uptime | grep '0 min'`
if [ -z "$UPTIME" ] && [ -n "$PPP0" ]; then
        echo -n "Log at ">> $LOGFILE
        date >> $LOGFILE
        uptime >> $LOGFILE
        sleep 3
        stopservice radvd
        sleep 1
        startservice radvd
        sleep 1
        grep radvd /var/log/messages | tail -6 >> $LOGFILE

Using putty to telnet into your device, and using built-in vi should do the job. Don’t forget to chmod 700 for the script.

This script will be called when WAN is up. The first boot up (by checking the uptime output) is fine, so no need to restart radvd service. For rest WAN up events, this script will restart radvd AGAIN for you.

DD-WRT did the restart on WAN up events already, but most of the time this is done a little bit early when working with HiNet. You’ll see radvd complains something like

no auto-selected prefix on interface br0, disabling advertisements

and IPv6 for LAN is gone. So I put a few sleep to make sure this workaround really works.

For PPPoE fixed IP v4 service, the workaround described above is required too, since HiNet does not provide fixed v6 prefix for PPPoE customers yet.

BTW, since USB storage is used, Entware is strongly recommended. That’s why I leave larger space for /opt. For my device, using Atheros install link works just fine. You can also do many other things by checking the Script Execution instructions.

digitalocean FreeBSD droplet network config gone after pkg update

Sort answer:

Boot to single user mode, edit /etc/rc.d/digitalocean
Change this line

# REQUIRE: var


# REQUIRE: var ldconfig

Long story:

I got a FreeBSD droplet in digitalocean, created long time ago. After a manual package maintenance and reboot, network of this droplet is gone.

During boot process, I also noticed these two unusual lines:

Shared object "libnghttp2.so.14" not found, required by "libcurl.so.4"
Shared object "libpython2.7.so.1" not found, required by "python2.7"

Of course these files are there, also confirmed by “ldconfig -p” output. Maybe this issue is related with rc order? After quick fix above applied, my droplet works again.

macOS Sierra, ssh key passphrase, and the Keychain

Tell macOS Sierra to stop Keychaining ssh key passphrase.

The behavior of ssh, ssh-agent and ssh-add, changed in macOS Sierra. There is no GUI pop up asking for ssh key passphrase to store the identity in ssh-agent. Instead, ssh asks you for the passphrase via command line prompt, then stores the passphrase in the Keychain. The worst part is, there’s no clue to delete that via Keychain Access. This isn’t quite right. Usually we expect ssh-agent stores our keys only, and the system will forget the identity after reboot. The concept is, the program can only remember the key but not the passphrase.

For people who want the old behavior, simply put these three lines in your ~/.ssh/config:

Host *
  UseKeychain no
  AddKeysToAgent yes

UseKeychain is a macOS only parameter, default yes. AddKeysToAgent is a new parameter introduced in OpenSSH 7, default no.

How about the passphrase previously stored in the Keychain?

First, using ssh-add to load your key into the agent again.
Then, using ssh-add -K -d to delete the key in agent and the passphrase in Keychain. Finally, using ssh-add -K to make sure nothing will be automatically loaded.

For those who still feel unhappy, find these files by find and delete them:

cd ~
find ./ -name "keychain-2.db*"

Though there’re some other stuff encrypted in it. Make sure there’s a backup before delete them.

Workaround for gogoc and freenet6 keepalive engine problem.

So many years passed, even after end of gogo6 project, still nobody found this out. Does anyone really use gogoc / freenet6 in daily life? Reason? icmp_echo_id in p_engine is uint16_t.

--- gogoc-tsp/src/net/icmp_echo_engine.c~	2016-07-22 15:16:32.382995000 +0800
+++ gogoc-tsp/src/net/icmp_echo_engine.c	2016-07-22 15:16:44.244691000 +0800
@@ -238,7 +238,7 @@
   p_engine->clbk_recv = recv_clbk;

   // Initialize engine socket variables.
-  p_engine->icmp_echo_id = pal_getpid();
+  p_engine->icmp_echo_id = pal_getpid() % 65536;
   p_engine->icmp_saf = af;
   switch( p_engine->icmp_saf )

Add utun support for gogoCLIENT

With some copy and paste work, it’s working now.

Utun support: utun works like OpenBSD’s tun. We need to take care of the first 4 bytes. That’s all.
Openssl: Since El Capitan, openssl headers are removed. So, use macports’s headers.

Code is on github https://github.com/evi1c/gogoc/commit/bd9af4101ac6134c90b61b01c78d140f68bae25e


% sw_vers
ProductName: Mac OS X
ProductVersion: 10.11
BuildVersion: 15A284

Build gogoc on OS X El Capitan

According to http://lists.apple.com/archives/macnetworkprog/2015/Jun/msg00025.html and test on OS X El Capitan with XCode 7.0.1, it’s not possible to build gogoc now. A quick fix for building this useful tiny utility, is to make use of macports. This is a quick hack. Need to do some research to understand how people deal with OS X without openssl header files.

diff -ruN gogoc-1_2-RELEASE~/gogoc-tsp/Makefile gogoc-1_2-RELEASE/gogoc-tsp/Makefile
--- gogoc-1_2-RELEASE~/gogoc-tsp/Makefile	2010-03-08 03:49:54.000000000 +0800
+++ gogoc-1_2-RELEASE/gogoc-tsp/Makefile	2015-10-03 21:09:45.000000000 +0800
@@ -61,7 +61,7 @@
 	$(PWD)/conf \
 LD_LIBRARIES=-lgogocpal -lgogocconfig -lgogocmessaging

% sw_vers
ProductName: Mac OS X
ProductVersion: 10.11
BuildVersion: 15A284

Using HiNet IPv6 tunnel broker on OS X.

HiNet is a popular ISP in Taiwan. Its IPv6 tunnel broker still works in year 2015. Why do I still need the tunnel broker, since the ISP provides native IPv6 service already? Because…

  1. I need IPv6 to work, apparently.
  2. I can only use native support in my home. Not in my office, not in my friend’s apartment.. etc.
  3. stf does not work behind NAT.

Okay it’s easy.

  1. You need gogoc-1_2-RELEASE.tar.gz. It’s ok to just pick it up from a FreeBSD distfile mirror.
  2. You need Xcode.
  3. You need tuntaposx.
  4. A little patch for gogoc-tsp/platform/darwin/tsp_local.c
    --- gogoc-1_2-RELEASE~/gogoc-tsp/platform/darwin/tsp_local.c 2010-03-08 04:08:27.000000000 +0800
    +++ gogoc-1_2-RELEASE/gogoc-tsp/platform/darwin/tsp_local.c 2015-09-12 03:31:50.000000000 +0800
    @@ -57,7 +57,7 @@
    void tspSetEnv(char *Variable, char *Value, int Flag)
    Display(LOG_LEVEL_3, ELInfo, "tspSetEnv", GOGO_STR_ENV_PRINT_VALUE, Variable, Value);
    - setenv(Variable, Value, Flag);
    + if ( Value != NULL ) setenv(Variable, Value, Flag);
    }// --------------------------------------------------------------------------
  5. Config it properly and run it.

Now it’s okay to test by Chrome. Navigate to ipv6.google.com. Okay to ping6 -c3 ipv6.google.com also.

If you want it work in Firefox, Safari, you need a workaroud. Assign a static IPv6 IP in your en0 or en1. A documentary IP 2001:db8::1/64 will work. It’s a OS X problem.


% sw_vers -productVersion
% cc -v
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix