<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Neil Bartley</title>
    <description>The latest articles on DEV Community by Neil Bartley (@neilbartley).</description>
    <link>https://dev.to/neilbartley</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F10732%2F3051568.jpeg</url>
      <title>DEV Community: Neil Bartley</title>
      <link>https://dev.to/neilbartley</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/neilbartley"/>
    <language>en</language>
    <item>
      <title>Calming App Jams with Træfik</title>
      <dc:creator>Neil Bartley</dc:creator>
      <pubDate>Mon, 29 Oct 2018 10:54:40 +0000</pubDate>
      <link>https://dev.to/neilbartley/calming-app-jams-with-trfik-3b7b</link>
      <guid>https://dev.to/neilbartley/calming-app-jams-with-trfik-3b7b</guid>
      <description>&lt;p&gt;This was originally posted on the &lt;a href="https://medium.com/flexmr-dev-blog/calming-app-jams-with-tr%C3%A6fik-c166b523ffff"&gt;FlexMR Dev Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.flexmr.net/"&gt;At FlexMR&lt;/a&gt; we make heavy use of a ‘prototype-first’ approach. We find it’s easier to produce a stand alone implementation of an integration with a third party tool (or idea) than spend time folding it into what we have, only to decide to throw it away and try a different way.&lt;/p&gt;

&lt;p&gt;As you’d expect this can produce a lot of apps. The configuration for NGINX (the ‘junction box’ of the server) started to become more unwieldy. New (and old) server configs and SSL certs started to pile up. Moving NGINX config to a separate git repository was tidier but it didn’t solve the underlying issue. I started to look around for an solution which better fitted our use case.&lt;/p&gt;

&lt;p&gt;Our infrastructure setup for prototypes (and as it happens, an internal tool called Hairy Slackbot — more on that in the future) lives on a dedicated server which is running Docker Swarm mode (so it is ready to scale when we need to).&lt;/p&gt;

&lt;p&gt;My wish list for a reverse proxy solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimal configuration, ideally on the app side&lt;/li&gt;
&lt;li&gt;Scalable&lt;/li&gt;
&lt;li&gt;Easily use &lt;a href="https://letsencrypt.org/"&gt;LetsEncrypt&lt;/a&gt; for certificate generation (provision and renew)&lt;/li&gt;
&lt;li&gt;Nice to have (only because we don’t need it right now): Load balancing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d looked at the popular &lt;a href="https://github.com/jwilder/nginx-proxy"&gt;nginx-proxy&lt;/a&gt; alongside &lt;a href="https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion"&gt;docker-letsencrypt-nginx-proxy-companion&lt;/a&gt; however, in the spirit of experimentation I thought I’d give the new one a whirl.&lt;/p&gt;

&lt;h3&gt;
  
  
  Træfik
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j9l9t-lw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/300/1%2AvmIbVVtdPASC7bHBvY7JAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j9l9t-lw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/300/1%2AvmIbVVtdPASC7bHBvY7JAA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Træfik is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Træfik integrates with your existing infrastructure components and configures itself automatically and dynamically. Pointing Træfik at your orchestrator should be the &lt;em&gt;only&lt;/em&gt; configuration step you need.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--69nvStY_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AtxAxvAwECxvFKHMQBQ8zjw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--69nvStY_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AtxAxvAwECxvFKHMQBQ8zjw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’re only going to touch a small portion of Træfik’s functionality in the example below. What we’re aiming to achieve here is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New services can be deployed to our development server without having to make any changes outside of that apps repository.&lt;/li&gt;
&lt;li&gt;New SSL certs are provisioned (and renewed) automatically by &lt;a href="https://letsencrypt.org/"&gt;LetsEncrypt&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Show me some code!
&lt;/h3&gt;

&lt;p&gt;Or, if you’re really keen there is a repository and example walkthrough in the next section.&lt;/p&gt;

&lt;h4&gt;
  
  
  What we had
&lt;/h4&gt;

&lt;p&gt;In the example I described above, I defined separate stacks for both the hsb and proto1 apps as well as nginx. nginx used to part of the hsb stack by virtue of it being the first stack on the development server, this was split out once we started adding more apps.&lt;/p&gt;

&lt;p&gt;Each app has its own git repository in which the docker stack file defines how it runs within the swarm (how many instances, memory and CPU restrictions, network details). We deploy via CI.&lt;/p&gt;

&lt;h4&gt;
  
  
  The new world
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k8qtvBcj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/890/1%2Abn2gW_eYr5V9VXQoN4106w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k8qtvBcj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/890/1%2Abn2gW_eYr5V9VXQoN4106w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Stack 1: træfik
&lt;/h4&gt;

&lt;p&gt;Deployed with: docker stack deploy --compose-file traefik-stack.yml --with-registry-auth traefik&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Stack 2: hsb
&lt;/h4&gt;

&lt;p&gt;Deployed with: docker stack deploy --compose-file hsb-stack.yml --with-registry-auth hsb&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Stack 3: proto1
&lt;/h4&gt;

&lt;p&gt;Deployed with: docker stack deploy --compose-file proto1-stack.yml --with-registry-auth proto1&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Visual view of configuration
&lt;/h4&gt;

&lt;p&gt;Traefik comes with a rather bonny UI, which we’ve configured to serve on port 8080 of the host. I access this via a SSH port forward eg: ssh -L8080:localhost:8080 ... as I don’t make it available externally (&lt;em&gt;and neither should you!&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rekKbX9J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANOiTcs0HgfAWsHzjYKpN3A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rekKbX9J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANOiTcs0HgfAWsHzjYKpN3A.png" alt=""&gt;&lt;/a&gt;The rather pretty &lt;em&gt;traefik UI&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Worked Example
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KIgRfNek--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/890/1%2AX3DjqSk4RL8sAn2y2Eyw9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KIgRfNek--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/890/1%2AX3DjqSk4RL8sAn2y2Eyw9A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The accompanying repo below uses a different setup to the hsb/proto1 setup above. I’ve done this to illustrate multiple services in the same stack and how single services can be assigned multiple domains.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/neilbartley"&gt;
        neilbartley
      &lt;/a&gt; / &lt;a href="https://github.com/neilbartley/traefik-swarm-example"&gt;
        traefik-swarm-example
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Traefik Swarm (mode) Example
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Traefik Swarm (mode) Example&lt;/h1&gt;
&lt;p&gt;Please see the accompanying &lt;a href="https://neil.bar" rel="nofollow"&gt;blog post&lt;/a&gt; for background.&lt;/p&gt;
&lt;h2&gt;
Running this example&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/208285" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/1ef9196a70d59cc7482bf34e200c4e0e1bccfe9d/68747470733a2f2f61736369696e656d612e6f72672f612f3230383238352e706e67" alt="asciicast"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/neilbartley/0d7cbe1042cbdccfd012ad808938420b"&gt;Commands&lt;/a&gt; and &lt;a href="https://vimeo.com/296966316" rel="nofollow"&gt;Video&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/neilbartley/traefik-swarm-example"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;I’m making use of &lt;a href="https://github.com/jwilder/whoami"&gt;jwilder/whoami&lt;/a&gt;.. This provides a web service which just echos its container id.&lt;/p&gt;

&lt;p&gt;Stack 1 is traefik, as above.&lt;/p&gt;

&lt;p&gt;Stack 2 is proto1, this has admin (proto1.neil.bar) and backoffice (proto4.neil.bar) services.&lt;/p&gt;

&lt;p&gt;Stack 3 is proto2, this has a single service, app (proto2.neil.bar and proto3.neil.bar).&lt;/p&gt;

&lt;p&gt;As we’ve set up the [acme] block in our traefik.toml then Traefik will automatically request, provision and renew certificates for the hosts defined in the traefik.frontend.rule label in each service from &lt;a href="https://letsencrypt.org/"&gt;LetsEncrypt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Adding additional services doesn’t require any changes to the traefik stack and with the &lt;a href="https://letsencrypt.org/"&gt;LetsEncrypt&lt;/a&gt; integration it really does make this task trivial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/208285"&gt;asciinema demo&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/296966316" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>docker</category>
      <category>traefik</category>
      <category>devops</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Wrestling Control of my Webcam</title>
      <dc:creator>Neil Bartley</dc:creator>
      <pubDate>Tue, 03 May 2016 20:24:01 +0000</pubDate>
      <link>https://dev.to/neilbartley/wrestling-control-of-my-webcam-3c6m</link>
      <guid>https://dev.to/neilbartley/wrestling-control-of-my-webcam-3c6m</guid>
      <description>&lt;p&gt;This post originally appeared (ages ago) on &lt;a href="https://neil.bar" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;. These devices are certainly still kicking around so the information is still relevant.&lt;/p&gt;

&lt;p&gt;A few months [now years] ago I ordered a generic IP webcam from Amazon. A &lt;a href="http://www.coolead.net/product/product-72-698.html" rel="noopener noreferrer"&gt;COOLEAD L610WS&lt;/a&gt; arrived the next day. The reason behind this purchase was to act as a baby monitor for our new daughter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkkWeGulyDlzNHJCbsQKQfQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkkWeGulyDlzNHJCbsQKQfQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Paranoid much?
&lt;/h3&gt;

&lt;p&gt;There has been much discussion about the security of &lt;a href="https://en.wikipedia.org/wiki/Internet_of_Things" rel="noopener noreferrer"&gt;IoT&lt;/a&gt; devices such as this webcam. This even broke out of the confines of geek sites and into the &lt;a href="https://www.theguardian.com/technology/2016/jan/25/search-engine-lets-users-find-live-video-of-sleeping-babies" rel="noopener noreferrer"&gt;mainstream press&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I knew that this device would be insecure when I purchased it. My view was that securing it was just a matter of changing the default passwords and updating the configuration — as I would do on any device I purchased.&lt;/p&gt;

&lt;p&gt;This was not the case and the more I dug, the more fail I found.&lt;/p&gt;

&lt;h4&gt;
  
  
  Danger!
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F480%2F1%2AU6BEvCPVOOKe45kIhu5N0Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F480%2F1%2AU6BEvCPVOOKe45kIhu5N0Q.jpeg"&gt;&lt;/a&gt;“I also use telnetd”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This webcam is massively insecure if you just plug it in and use.&lt;/li&gt;
&lt;li&gt;Even if you spend some time updating passwords and configuration, it is not much better.&lt;/li&gt;
&lt;li&gt;The firmware and set-up do not look to have seen any form of quality control.&lt;/li&gt;
&lt;li&gt;By default this webcam is immediately accessible from the internet and due to some bad code, can’t be disabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  External Access
&lt;/h4&gt;

&lt;p&gt;In an attempt to make it easy for people to view the webcam from outside the confines of their home network, a number of options are typically offered by these sorts of device:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The webcam will use a p2p system and open up ports on your router via &lt;a href="https://en.wikipedia.org/wiki/Universal_Plug_and_Play" rel="noopener noreferrer"&gt;UPnP&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can upload images to an FTP site.&lt;/li&gt;
&lt;li&gt;You can send images via email.&lt;/li&gt;
&lt;li&gt;The documentation will suggest opening up ports on your router to allow access.&lt;/li&gt;
&lt;li&gt;A dynamic domain name service (DDNS) will ensure you can always connect, even if your router changes IP.&lt;/li&gt;
&lt;li&gt;An even scarier alternative is that the webcam will upload images/footages to the &lt;strong&gt;manufacturer’s servers&lt;/strong&gt; for you to view from their website.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My webcam offers a p2p system, a dynamic name service, FTP upload and email.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Browser
&lt;/h4&gt;

&lt;p&gt;Plugging in the webcam and browsing to the IP address serves me a standard HTTP authentication screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F784%2F1%2Aicp_rxzEAYSzVJD58HzpOA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F784%2F1%2Aicp_rxzEAYSzVJD58HzpOA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note ‘Your connection to this site is not private’. This means that your user name and password are sent over the network (or internet) in cleartext and can be trivially intercepted.&lt;/p&gt;

&lt;p&gt;After authentication, you are presented with a number of options to view your camera based on your OS/browser (IE, not IE, mobile).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARMR-TgQid090L7-rzwZ33A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARMR-TgQid090L7-rzwZ33A.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The IE option offers the download of some software via a link which helpfully includes your username and password. I’d go &lt;strong&gt;nowhere&lt;/strong&gt; near any software bundled with this webcam — I don’t need it and would not trust it anyway.&lt;/p&gt;

&lt;p&gt;So far, nothing I have seen is instilling any confidence in the software. Let’s inspect the page which displays the video/image from the webcam:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANP6tY5PwGsaPUhEc23mS2A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANP6tY5PwGsaPUhEc23mS2A.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That looks like commented out development code. It also betrays the default admin user and password (&lt;em&gt;admin,&lt;/em&gt; with no password).&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration
&lt;/h4&gt;

&lt;p&gt;I tried locking down the DDNS configuration on this device but I can’t. The option is there, but my choice is not actioned or even saved after clicking either of the mislabelled buttons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2GRnHZ4XY7SRehf5VcfhAg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2GRnHZ4XY7SRehf5VcfhAg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A look at the source shows more commented out code, this time its JS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AB9hXqy19cf-kcPqRMlX8qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AB9hXqy19cf-kcPqRMlX8qw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to that code snippet, the following request &lt;em&gt;would&lt;/em&gt; disable DDNS. I don’t trust this device though.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;There is &lt;strong&gt;no&lt;/strong&gt; option in the admin section to turn off the p2p option. I’d guess it probably would not have worked anyway!&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;script&lt;/em&gt; declarations at the top of the index file reference a couple of cgi files. These are used to set variables for &lt;strong&gt;every&lt;/strong&gt; configuration option for each page. Let’s take a look at them.&lt;/p&gt;

&lt;h4&gt;
  
  
  get_status.cgi
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  get_params.cgi
&lt;/h4&gt;

&lt;p&gt;Highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username and passwords for all other users.&lt;/li&gt;
&lt;li&gt;Network configuration, including the SSID and WiFi password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;(I’ve stripped out some consecutive variables to save some lines).&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  set_alias.cgi
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F874%2F1%2Aqvr6RdW0yP_Tfn0IXeOSMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F874%2F1%2Aqvr6RdW0yP_Tfn0IXeOSMg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This script is used to set the alias of the device — to give it a friendly name. I decided to pick on this particular &lt;a href="https://en.wikipedia.org/wiki/Common_Gateway_Interface" rel="noopener noreferrer"&gt;cgi&lt;/a&gt; as it is simple (one value) and is displayed on most (if not all) pages outside of the admin area.&lt;/p&gt;

&lt;p&gt;What I was looking for was a &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting" rel="noopener noreferrer"&gt;cross site scripting (XSS)&lt;/a&gt; vector.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Credit to&lt;/em&gt; &lt;a href="http://www.drolez.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Lud&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for beating me to it &lt;em&gt;[_here&lt;/em&gt;](&lt;a href="http://www.drolez.com/blog/?category=Hardware&amp;amp;post=jw0004-webcam" rel="noopener noreferrer"&gt;http://www.drolez.com/blog/?category=Hardware&amp;amp;post=jw0004-webcam&lt;/a&gt;)&lt;/em&gt;._&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWsEIT9JvTgs1_GE9hXPrZw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWsEIT9JvTgs1_GE9hXPrZw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now look what happens when I log in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AaxcmjuVqqk0mniqvELqZhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AaxcmjuVqqk0mniqvELqZhw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I expect the other forms which take text input are equally as susceptible, but are likely limited to the admin pages.&lt;/p&gt;

&lt;p&gt;The XSS injected here is a harmless popup but it is not inconceivable that something much more malicious could be cooked up. As &lt;a href="http://www.drolez.com/" rel="noopener noreferrer"&gt;Lud&lt;/a&gt; points out, the lack of &lt;a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="noopener noreferrer"&gt;cross site request forgery (CSRF)&lt;/a&gt; protection could allow the users browser to be taken over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Device
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Firewall Logs
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;I'm going to guess the latter three servers are something to do with the p2p functionality of this webcam. &lt;em&gt;I’ll maybe investigate these further with&lt;/em&gt; &lt;a href="https://www.wireshark.org/" rel="noopener noreferrer"&gt;&lt;em&gt;Wireshark&lt;/em&gt;&lt;/a&gt; &lt;em&gt;at some point.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  54.247.103.91
&lt;/h4&gt;

&lt;p&gt;This looks to be a box hosted with AWS (in Ireland).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F646%2F1%2AQqbqezCJJ7YgiuwXcsizRg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F646%2F1%2AQqbqezCJJ7YgiuwXcsizRg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hitting this on port 80 returns the following from a very online Apache 2.2.22 instance.&lt;/p&gt;

&lt;h4&gt;
  
  
  54.217.201.148
&lt;/h4&gt;

&lt;p&gt;This looks to be an Ubuntu box, also hosted with AWS (in Ireland).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F970%2F1%2Ad65HhWTWuTgF3J2HXr5SGg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F970%2F1%2Ad65HhWTWuTgF3J2HXr5SGg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Port 80 gives up a default configured Apache 2.2.22 instance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Others
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;128.138.141.172 — This is an NTP server at the University of Colorado.&lt;/li&gt;
&lt;li&gt;54.245.98.57 — Another AWS box located in the US.&lt;/li&gt;
&lt;li&gt;123.56.159.92 — This is a box located in Hangzhou, Zhejiang, China and is hosted by Aliyun Computing Co.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Services
&lt;/h3&gt;

&lt;p&gt;Let’s see what services are running on the device. We’ll use the stalwart of network scanners, &lt;a href="https://nmap.org/" rel="noopener noreferrer"&gt;nmap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The options used are;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;-sS — Scan TCP ports (SYN)&lt;/li&gt;
&lt;li&gt;-sU — Scan UDP ports&lt;/li&gt;
&lt;li&gt;-sV — Try and figure out what version of the service is running&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Telnet
&lt;/h4&gt;

&lt;p&gt;Telnet has no place on this device. It certainly shouldn't be enabled by default and I wonder why it is. Its worth noting that the username and password which is set for the web interface does not work here.&lt;/p&gt;

&lt;p&gt;Let’s point &lt;a href="https://www.metasploit.com/" rel="noopener noreferrer"&gt;Metasploit&lt;/a&gt; at this and see if we can get a login.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.metasploit.com/" rel="noopener noreferrer"&gt;Metasploit&lt;/a&gt; is a framework for developing and executing exploit code against a remote target machine. It comes bundled with a bunch of scanners. We’ll make use of &lt;em&gt;auxiliary/scanner/telnet/telnet_login&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I've presumed that the &lt;em&gt;root&lt;/em&gt; account is going to be accessible (and not locked down by disabling its access). This presumption is based on what I have seen so far.&lt;/p&gt;

&lt;p&gt;It took &lt;a href="https://asciinema.org/a/5voi0pypq2b8kxx6ysa7o7nqk" rel="noopener noreferrer"&gt;less than 3 minutes&lt;/a&gt; to find that ‘123456’ was the root password.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lots of people have beat me to this!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;PenTestPartners — Hacking the IP Camera: &lt;a href="https://www.pentestpartners.com/blog/hacking-the-ip-camera-part-1/" rel="noopener noreferrer"&gt;part 1&lt;/a&gt; | &lt;a href="https://www.pentestpartners.com/blog/hacking-the-aldi-ip-cctv-camera-part-2/" rel="noopener noreferrer"&gt;part 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Krebs on Security — &lt;a href="http://krebsonsecurity.com/2016/02/this-is-why-people-fear-the-internet-of-things/" rel="noopener noreferrer"&gt;This is Why People Fear the ‘Internet of Things’&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lud’s open source corner — &lt;a href="http://www.drolez.com/blog/?category=Hardware&amp;amp;post=jw0004-webcam" rel="noopener noreferrer"&gt;Wanscam JW0004 IP Webcam hacking&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F850%2F1%2AGqb46Q9cRX3ECVt0g-qJSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F850%2F1%2AGqb46Q9cRX3ECVt0g-qJSA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The IoT is great — you can pick up a wireless infra-red webcam for under £30. However, you get what you pay for.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The firmware makes use of insecure technologies (telnet, FTP, no SSL on web, SMTP) which allow for data to be easily intercepted.&lt;/li&gt;
&lt;li&gt;The software seems to have been clobbered together without any thought for best practices, security, review or testing.&lt;/li&gt;
&lt;li&gt;The infrastructure the device talks to doesn't give me any confidence — a service which displays a default (Apache) page has not been configured correctly. I’d not fancy trusting it with my personal information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It seems that these devices, which look to be essentially the same but made by different companies, all use a similar software base. This is then tweaked occasionally at the whim of the given manufacturer.&lt;/p&gt;

&lt;p&gt;These devices are not aimed at tech-savvy individuals and most people won’t know how easily these can be exploited by inquisitive or malicious parties.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The only way I can see to safely use this webcam is to prevent the device from accessing the internet at all.&lt;/p&gt;

&lt;p&gt;At this point my ‘Internet of Things’ device is more accurately an ‘of Things’ device.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Ghosts?
&lt;/h3&gt;

&lt;p&gt;This is a question which I’d not considered when making my choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANcGjQkZM-RILny5QcyipDA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ANcGjQkZM-RILny5QcyipDA.png"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>security</category>
      <category>iot</category>
      <category>hacking</category>
    </item>
    <item>
      <title>A really simple Slack integration in Rails</title>
      <dc:creator>Neil Bartley</dc:creator>
      <pubDate>Wed, 06 May 2015 22:17:00 +0000</pubDate>
      <link>https://dev.to/neilbartley/a-really-simple-slack-integration-in-rails-jag</link>
      <guid>https://dev.to/neilbartley/a-really-simple-slack-integration-in-rails-jag</guid>
      <description>&lt;p&gt;I’m a big fan of &lt;a href="https://slack.com" rel="noopener noreferrer"&gt;Slack&lt;/a&gt;. One of its strengths is the large list of &lt;a href="https://slack.com/integrations" rel="noopener noreferrer"&gt;integrations&lt;/a&gt; that it provides ‘out of the box’. I’ll cover another strength later (when I get my soap box out!).&lt;/p&gt;

&lt;p&gt;Clearly, there isn’t likely to be an integration for ‘my bespoke rails webapp’ but Slack have you covered by supplying a framework to allow incoming notifications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F692%2F1%2A3wBSCaJlHSk1kuq3losm_A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F692%2F1%2A3wBSCaJlHSk1kuq3losm_A.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m going to take advantage of this to send event details from ‘my bespoke rails webapp’ to Slack.&lt;/p&gt;

&lt;h4&gt;
  
  
  Real life use case
&lt;/h4&gt;

&lt;p&gt;The application which I develop, has a bunch of internal mailers hanging off it. These send mails to specified people when certain actions have occurred. In this example we’ll take the case of &lt;strong&gt;‘someone clicking the wibble button’&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Soap Box
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWkrhMp77kTaZey5jpP3J7A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWkrhMp77kTaZey5jpP3J7A.jpeg"&gt;&lt;/a&gt;&lt;a href="https://creativecommons.org/licenses/by/2.0/" rel="noopener noreferrer"&gt;Creative Commons&lt;/a&gt; by &lt;a href="https://www.flickr.com/photos/bmcirillo/" rel="noopener noreferrer"&gt;Brandon C&lt;/a&gt;. No changes were made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Email sucks&lt;/em&gt;&lt;/strong&gt;. I get too much of it (I probably send too much as well). By allowing these mailers to exist (and by adding new ones), I’m perpetuating this pain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4xhTahwmWxmg9ny4Dty86Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A4xhTahwmWxmg9ny4Dty86Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the ‘DIY Integrations’ section of the Slack admin interface you’ll see the option to add ‘Incoming Webhooks’. Select this and choose the default channel you’d like your notifications to appear in (this can be overriden on a case by case basis).&lt;/p&gt;

&lt;p&gt;What we need from this is a unique ‘Webhook URL’. Once we have this, we can start putting together a payload.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aj68Z2uqT4mmHlYKWdL9ECg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aj68Z2uqT4mmHlYKWdL9ECg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Specification
&lt;/h4&gt;

&lt;p&gt;I’m not going to copy-paste the fine documentation produced by Slack. Instead, here are some links!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://api.slack.com/incoming-webhooks" rel="noopener noreferrer"&gt;https://api.slack.com/incoming-webhooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.slack.com/docs/attachments" rel="noopener noreferrer"&gt;https://api.slack.com/docs/attachments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  At last, some code!
&lt;/h4&gt;

&lt;p&gt;Add your webhook URL and test channel to your development &lt;em&gt;application.yml&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The webhook URL will likely stay the same in your production environment, but you may want to update the channel name.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;{gist &lt;a href="https://gist.github.com/neilbartley/f1ac92cf40f79a789e64" rel="noopener noreferrer"&gt;https://gist.github.com/neilbartley/f1ac92cf40f79a789e64&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;I’ve created a service for our our SlackBot, which could simply be called from the controller.&lt;/p&gt;

&lt;p&gt;{gist &lt;a href="https://gist.github.com/neilbartley/87bbcb97c67617d16344" rel="noopener noreferrer"&gt;https://gist.github.com/neilbartley/87bbcb97c67617d16344&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;To demonstrate, lets call from rails console:&lt;/p&gt;

&lt;p&gt;{gist &lt;a href="https://gist.github.com/neilbartley/21d1d6e1d4ffb09700c9" rel="noopener noreferrer"&gt;https://gist.github.com/neilbartley/21d1d6e1d4ffb09700c9&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;Line two will produce the following notification in the #events_test channel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F966%2F1%2AeUHKRxHgLaVjXiLMOZhC8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F966%2F1%2AeUHKRxHgLaVjXiLMOZhC8A.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lines four and six illustrate overriding the default channel to another channel or user.&lt;/p&gt;




</description>
      <category>ruby</category>
      <category>rails</category>
      <category>slack</category>
      <category>integration</category>
    </item>
  </channel>
</rss>
