Just one geek's opinions and epiphanies

CenturyLink Technicolor C2100T Firewall Settings

Hey Friends! After having a ton of issues with services from CenturyLink this week I decided I needed to reset my router that they provided me.

The router they have provided me is the Technicolor C2100T. This all relates to that particular device.

After resetting the router to it's default settings, I decided to take a look at the firewall settings. This is what I found:

screen capture of router firewall rules

Yeah, they have TONS of defined ports and protocols that are wide open to the world. Oh wait... what is that last one?

trimmed screen cap showing undefined ports

THEY LITERALLY OPEN EVERY SINGLE PORT ON THE DEVICE! Let me say that again... the CenturyLink Technicolor C2100T is a gaping huge hole into your home network. You can literally walk right past the router on ANY PORT.

Reading Goal 2017

Reading Goal 2017

I've decided to make a public reading goal this year. I'm committing myself to reading 12 books that are unrelated to my work. You can follow my progress here and at Goodreads.

Currently I'm reading The Ghost Brigades by John Scalzi.

Syncthing & Systemd: For Fun

So a while ago I heard about Syncthing on the GoTime.FM Podcast, and I decided to finally get Syncthing running on my local systems.


Syncthing replaces proprietary sync and cloud services with something open, trustworthy and decentralized. Your data is your data alone and you deserve to choose where it is stored, if it is shared with some third party and how it's transmitted over the Internet.

The above quote is from Syncthing's site. Syncthing is an Open Source software that syncs things across the internet. No matter where your machines are, as long as they are connectable. They even have a version for Android available at Google Play, or on F-Droid.

How I'm using Syncthing

So my new job has me working as a road warrior. This means I have a laptop that I use a lot for work while I am remote. However, my machine at home (nicknamed: Beast) has better processing power, more memory, and as a result performs much better than the laptop.

The first thought I had was, how can I make the process of working on code less painful by getting code from my laptop to Beast and back? Syncthing to the rescue!

Setting up Syncthing

First you have to get Syncthing installed. This is easy as almost all OSes and distros are supported. I found that Fedora isn't supported directly, so I just grabbed the tarball and extracted it in /usr/local/syncthing

# Untar tarball to ~/.local
$ sudo tar xvzf ~/Downloads/syncthing.tar.gz -C /usr/local/

To make executing Syncthing easy, you can symlink the executable into your path

$ sudo symlink /usr/local/syncthing/syncthing /usr/local/bin/syncthing

When you successfully run Syncthing a browser will open with your new running instance of Syncthing!

Introduce your Devices

So once you have it running you have to establish Devices. What do you want to sync between, basically. I am syncing between Beast, Lenovo, and OPO (my Android based phone).

To do this you start Syncthing on each of the devices, and then share the device ID from each node. A hint here, if you use your Android as the Introducer you save yourself some work.

Sync your Things!

Finally you are ready to sync things. From the machine where the things exist now, you add a Folder and tell it what to share (the actual path) and then which devices to share it to. There are advanced options for timing, and master/normal sharing. I won't cover those but they are available.


Now, having Syncthing running when you fire up the executable is great, but wouldn't it be nice if Syncthing just started and did it's work each time you boot your machine?

No problem, just create a systemd .service and then enable it. Here is how I did mine.

# Create a group and user for Syncthing
$ sudo groupadd syncthing
$ sudo useradd -g syncthing syncthing

# Create .service file
vim /etc/systemd/system/syncthing@syncthing.service  
# systemd service file for Syncthing
Description=Syncthing - Open Source Continuous File Synchronization for %I  

ExecStart=/usr/local/bin/syncthing -no-browser -no-restart -logflags=0  
SuccessExitStatus=3 4  
RestartForceExitStatus=3 4


Finally enable Syncthing at startup

# Enable and Start Syncthing
$ sudo systemctl enable syncthing@syncthing.service
$ sudo systemctl start syncthing@syncthing.service

You now have Syncthing running at boot, and in the background.


If you happen to run into problems with starting Syncthing via systemd, you might want to test if SELinux is the problem.

# Check audit log for syncthing
$ sudo cat /etc/log/audit/audit.log | grep syncthing
# Temporarily disable SELinux
$ sudo setenforce 0

If you find an error or disabling SELinux allows Syncthing to run then you need to adjust the labels of the executable (most likely). However, that is out of scope for this article.

Late but worth the wait...

I have finally updated my blog to Ghost 0.9.0, but I have to be honest, I think this might be the last version of my blog on Ghost. Now that I am working with Go much more, I am giving some serious consideration to using Hugo to generate a static build site. Not that my server is over burdened by the traffic I am getting, but the static site, for obvious reasons seems like a good way to go. Who knows?

Onward to the future!

Broadcast Communication in Golang

Today I set out to understand a few different ways of running an infinite loop with controlled stopping. Perhaps better known as a Daemon. Ok, daemons have lots of other features, but the gist is this... it's a loop, that accepts signals, and reacts upon them accordingly.

To that end, I came up with the code below for running a Daemon in Golang, that responds to UNIX Signals, and has multiple workers listening to the same channel and reacting in sync.

Note: The main function also alerts the works when to stop.

First, take note I called what I use a channel, that isn't 100% true. Yes, I use some channels, but the workers are actually listening to a sync.Cond, and reacting to the sync.Cond.Broadcast() method. You'll also note that I extended the sync.Cond struct into MySyncCond and added Payload and Kill fields. These allow me to not only wake the workers, but also tell them important information.

Hopefully my inline comment and docblocs do this justice, if not please feel free to reach out to me.

package main

import (

// Extend the sync.Cond struct to add Kill, and Payload
type MySyncCond struct {
    Kill    bool
    Payload int

// Add an Init() and set Kill to false (declaritive)
func (m *MySyncCond) Init() {
    m.Kill = false

// Extend sync.Cond.Broadcast() to allow a payload
func (m *MySyncCond) Broadcast(payload int) {
    // set the new payload before broadcasting
    m.Payload = payload
    // call sync.Cond.Broadcast()

// first worker, generates message to be broadcast out
func pinger(c *MySyncCond, wg *sync.WaitGroup) {

    defer wg.Done() // alert the waiting group we are done
    defer c.L.Unlock() // make sure we unlock the condition
    defer log.Println("Terminated pinger") // log a message that we are done here

    // Loop, and send out pings
    count := 0
    for {
        count += 1
        log.Printf("Pinger Pings: %d\n", count)
        // here I use the extended MySyncCond.Broadcast() that allows a payload to be passed
        time.Sleep(5 * time.Second)

// our second worker, checks if the ping count is divisible by 1 (true)
// Note: The infinite loop only breaks when the sync.Cond has the field Kill == true
func divByOne(c *MySyncCond, wg *sync.WaitGroup) {
    defer wg.Done() 
    defer c.L.Unlock() // make sure we unlock
    defer log.Printf("Terminated divByOne")

    for {
        // here I evaluate the Kill field of the MySyncCond struct
        if c.Kill {
        // here I evaluate the Payload field of the MySyncCond struct
        if c.Payload%1 == 0 {

// basically the same as divByOne, but by 2
func divByTwo(c *MySyncCond, wg *sync.WaitGroup) {
    defer wg.Done()
    defer c.L.Unlock() // make sure we unlock
    defer log.Println("Terminated divByTwo")

    for {
        if c.Kill {
        if c.Payload%2 == 0 {

// yet another worker, this one divides by 3
func divByThree(c *MySyncCond, wg *sync.WaitGroup) {
    defer wg.Done()
    defer c.L.Unlock()
    defer log.Println("Terminated divByThree")
    for {
        if c.Kill {
        if c.Payload%3 == 0 {

// Where the magic starts
func main() {
    // write all the logs to a known file
    logfile, err := os.OpenFile("/tmp/condfun.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
    if err != nil {
    // make sure we close the file handler
    defer logfile.Close()

    // Create a new Lock (Mutext), pass it to a new sync.Cond, and the push the sync.Cond into MySyncCond (thus extending it)
    c := MySyncCond{sync.NewCond(new(sync.Mutex)),  false, 0}

    // our first channel, this is used to tell Main that the Waiter is done.
    done := make(chan bool)

    // Kill channel, used to catch Unix Signals
    kill := make(chan os.Signal)
    defer close(kill) // let's make sure to close the channel when we are done!
    signal.Notify(kill) // the magic here assigns Unix Signals to be passed to our channel

    var wg sync.WaitGroup // create a WaitGroup

    wg.Add(4) // tell our WaitGroup how many workers we have
    // fire off all our workers
    // each of these must call wg.Done() or else this whole thing falls apart, hence the defer wg.Done() they all call. To further enforce this we could have used and interface, but that seemed like real work
    go pinger(&c, &wg)
    go divByOne(&c, &wg)
    go divByTwo(&c, &wg)
    go divByThree(&c, &wg)

    // out anonymous worker, this waits for all things in the WaitGroup to complete, if that happens it will pass true to the done channel
    go func(wg *sync.WaitGroup, done chan bool) {
        defer close(done)
        done <- true
    }(&wg, done)

    select {
    case <-kill: // handle the kill signal
        log.Println("Kill Seen")
        c.Kill = true
    case <-done: // handle the Waiter finishing (signals all workers stopped)
        log.Println("All workers have reported done")

    log.Println("Terminated Main")

As things always are, as I am writing this I realize now that there is the potential for the workers to fail, and I don't handle the errors, but this is more about the synchronous communication between workers.