Monthly Archives: October 2023

Simple Single Page Site with Secure Log Access

3 minutes, 36 seconds

And image of the sticker with a ".xyz" TLD

A friend of mine created some fun stickers for use at the most recent DEF CON. They were sly commentary about how corporate a lot of the stickers are and how maybe we should get back to our DIY roots. But…what’s this? There’s a .xyz in there…is that a TLD…is there domain I could go to?! IS THIS STICKER AN AD ITSELF?!?!?!?!1!

(Sticker image is marked with CC0 1.0)

It’s all of those things and none of those things – that’s why I love it so much. Best of all, when you go to website, you get just what you deserve ;)

The website was initially setup on a free hosting provider, but they didn’t provide any logs – something my friend was curious about to see how much traffic the non-ad ad was generating. I have a VERY cheap VPS server that already had Ubuntu server and Caddy on it, and I figured I could help by hosting a wee single file static web site and be able to easily offer the logs. Let’s see what we can do!

Step 1: One HTML file + Four Caddy config lines = Web server

I frickin’ love Caddy! I made a single index.html file and then added these 4 lines of config:

the-domain-goes-here.xyz {
        root * /var/www/the-domain-goes-here.xyz
        file_server
}

After I restarted Caddy (systemctl restart caddy) – I was all set! As DNS had already been changed to point to the IP of my lil’ server, Caddy auto-provisioned a free Let’s Encrypt cert, redirected all traffic from port 80 -> 443 and the site worked perfectly!

By default Caddy has logs turned off – let’s fix that!

Step 2: Turn up the (log) volume

Unsurprisingly, Caddy makes enabling logs very straight forward. Just add these three lines

  log {
    output file /var/log/caddy/the-domain-goes-here.xyz-access.log
  }

I reloaded the config in Caddy (systemctl reload caddy) and checked for log activity in /var/log/caddy/. It was there! Oh…it was there in full repetitive, verbose JSON…OK, cool, I guess that’s a sane default in our new cloud init all JSON/YAML all the time world. However, how about common log format though?

This was the first time Caddy surprised me! While it was easy enough to do (huge props to “keen” on Stack Overflow), it was a bit more convoluted and verbose than I expected. You have to change the log deceleration to be log access-formatted and then specify both a format and a transform. The final full server config looks like this:

the-domain-goes-here.xyz {
	root * /var/www/the-domain-goes-here.xyz
	file_server
	log access-formatted {
    		output file /var/log/caddy/the-domain-goes-here.xyz-access.log
		# OMG - thank you!! https://stackoverflow.com/a/76988109
		format transform `{request>remote_ip} - {request>user_id} [{ts}] "{request>method} {request>uri} {request>proto}" {status} {size} "{request>headers>Referer>[0]}" "{request>headers>User-Agent>[0]}" "host:{request>host}"` {
          time_format "02/Jan/2006:15:04:05 -0700"
       		}
  	}
}

Now let’s figure how to to add secure access to download those logs.

Step 3: Rsync via Authorized Keys FTW!

A straight forward way to give access to the logs would be to create a new user (adduser username) and then update the user to be able to read the files created by the Caddy process by adding them to the right group (usermod -a -G caddy username). This indeed worked well enough, but it also gave the user a full shell account on the web server. While they’re a friend and I trust them, I also wanted see if there was a more secure way of granting access.

From prior projects, I knew you could force an SSH session to immediately execute a command upon login, and only that command, by prepending this to the entry in the authorized_key file:

command="SOME_COMMAND",no-port-forwarding,no-user-rc SSH-KEY-HERE

If I had SOME_COMMAND be /usr/bin/rsync then this would be great! The user could easily sync the updates to their access log file at /var/log/caddy/the-domain-goes-here.xyz-access.log. but then I realized they could also rsync off ANY file that they had read access too. That’s not ideal.

The final piece to this Simple Single Page Site with Secure Log Access is rrsync. This is a python script developed specifically for the use case of allowing users to rsync only specific files via the Authorized Keys trick. The full array of security flags now looks like this:

restrict,command="/usr/bin/rrsync -ro /var/log/caddy/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding SSH-KEY-HERE

As there’s no other logs in /var/log/caddy – this works great! The user just needs to call:

rsync -axv username@the-domain-goes-here.xyz: .

Because of the magic of rrsync (two rs) on the server forcing them into a specific remote directory, the rsync (one r) on client is none the wiser and happily syncs away.

Happy web serving and secure log access syncing and Happy Halloween!

Blog Theme Improvements

2 minutes, 38 seconds

Most of the time when I’m reading articles online, I very often switch my browser to Reader View. This gets rid of all fluff of display and theme that a site’s have and, most importantly, fixes the low contrast text trend. Reader View is white text on black background (but this is configurable) and also adds a “Time to Read” at the top of the article. The latter prevents me from clicking on a “quick read” which is actually 30 min!

I noticed some times I visit a site and don’t flip in Reader View because they’ve done it for me already! While I know not everyone is like me, so they may prefer miles of white space with a nice, thin, light gray font on an off-white background. However, as this is my blog, I’ve just converted to be just as I like those sites where I don’t turn on Reader View!

Referencing the image above, here’s’ the changes with the “before” on the right and the “after” on the left:

  1. All code blocks are now numbered. They’re still zebra striped, but they’re higher contrast
  2. Text is now larger and easier to read – straight up white on black
  3. White background is now black background*
  4. Items that are variables or code snippets have a different colored background, like this
  5. The read time is shown at the top of every post (not pictured)
  6. Removed “Share This” icons at the bottom of each post (also not pictured)

* – I actually don’t force the black background! All the changes are live based on the users’ OS preference via the prefers-color-scheme CSS selector. You can pick! Here’s a video showing the two flipping back and forth:

I’m still tweaking a few of the CSS colors and what not as I find things not quite right, but please send along any questions or comments. I’d love to hear what y’all think!

Addendum

The “Share This” plugin mentioned above was not only adding some extra clutter of icons I no longer thought too helpful, but was also including an external CSS or JavaScript or something file that didn’t feel right given I don’t prefer to share my HTTP traffic with any other sites.

As well, I removed two extensions (Share This and Code Highlighter syntax) which I then implemented in my own wee plugin. Less 3rd party code means less to update means less security concerns for my ol’ blog here. As well, I greatly reduced the feature set and amount of PHP – I think the plugin is about 5 active lines of PHP.

Finally, I’m using the Twenty Twelve theme with this additional CSS (added via “appearance” section of prefs):

#site-navigation, .comments-link { 
    display:none;
}
.wp-block-quote {
    border-left: .25em solid;
    border-left-width: 0.25em;
    border-left-style: solid;
    border-left-color: cyan;
}
body .site {
    margin-top: 0;
    margin-bottom: 0;
}
body, * ,.site {
    font-size: 1.15rem;
}
body {
    background-color: white;
    color: black;
}
.wp-block-code ol li:nth-child(odd), code  {
    background: lightcyan;
}
code {
    padding: 4px 6px 4px 6px;
}
@media screen and (prefers-color-scheme: dark) {
     *,.site  {
        background-color: black;
        color: white;
    }
    .widget-area .widget a, .entry-content a, .comment-content a {
        color: #51c9ff;
    }
   .widget-area .widget a:visited,.widget-area .widget a,.entry-content a:visited, .comment-content a:visited {
        color: lightgray;
    }
    .widget-area .widget a:hover ,.widget-area .widget a,.entry-content a:hover, .comment-content a:hover {
        color: white;
    }
    body {
        background-color: #010149;
    }
    .wp-block-code ol li:nth-child(odd), .wp-block-code ol li:nth-child(odd) {
        background: #000030;
        color:white;
    }
    code {
        background: #000065;
    }
    .entry-content img, .comment-content img, .widget img, img.header-image, .author-avatar img, img.wp-post-image, .wp-block-embed {
        border-radius: 3px;
        box-shadow: 1px 2px 5px rgba(255, 255, 255, 0.84);
    }
}

With all this you should able able to reproduce these settings on your own blog if you so desire!