Plugging TSL into your Go Backend - for free!

agolangf · · 788 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I don&#39;t think I need sell anyone on the concept that securing client-server traffic is a good idea. These days we can even do it for free through Let&#39;s Encrypt.</p> <p>-- This post is by and large a a ctrl-c ctrl-v from my (very) <a href="https://dybings.blogspot.no/" rel="nofollow">little blog.</a></p> <p>-- Errata: Should be TLS <em>doh</em> edited... but title stands, nothing I can do about it.</p> <p>In my example of how to implement it, I&#39;ll assume running an Ubuntu server. First order of business is getting Let&#39;s Encrypts&#39; Certificate Generator up and running on your system, cutely named Certbot. This will create your TLS certificate, and later update it.</p> <p>The one downside of using Let&#39;s Encrypt is that the certificates only last 3 months before needing to be re-issued. If you&#39;re clever, you&#39;ll have your backend do it automatically by either generating new ones on each deploy (assuming reasonably high frequency of updates) and/or during daily Cron jobs, check the timestamp of the certificate files, and renew if getting close to the expiration date.</p> <p>Another gotcha is that Let&#39;s Encrypt won&#39;t issue certificates to typical AWS domain names like &lt;ec2-12-123-12-123.eu-central-1.compute.amazonaws.com&gt; as these servers can easily be used for various nefarious purposes. So you&#39;re going to need a proper address to plug into your certificate. Any DNS service will let you point to your AWS EC2 instance, so it&#39;s no biggie. If you already got one, say for a website, just set up a subdomain there that points to your AWS IP.</p> <p>I&#39;ll not go into those topics in any detail here though. So moving on, the very first thing on the agenda, is installing Certbot and generating the certificates.</p> <p>Once you&#39;ve SSH&#39;ed into your server, this will get you the bot:</p> <pre><code>$ sudo apt-get update $ sudo apt-get install software-properties-common $ sudo add-apt-repository ppa:certbot/certbot $ sudo apt-get update $ sudo apt-get install certbot </code></pre> <p>Next, since we&#39;re not running some external webserver or anything like that, but let the goodness of Go do it for us, we&#39;ll need a &#39;standalone webserver&#39; certificate that we can use.</p> <pre><code>$ sudo certbot certonly --standalone -d katzrule.com -d www.katzrule.com </code></pre> <p>This will create the two files you need import into your Go app. You&#39;ll find them under &#39;/etc/letsencrypt/live/katzrule.com/&#39; and they should be named &#39;fullchain.pem&#39; and &#39;privkey.pem&#39;.</p> <p>How you import them into Go is a matter of preference. I&#39;m a bit lazy, so I didn&#39;t want to comment in and out the loading of the certs for when developing (just testing using localhost) and when deploying (running live on AWS). So I set up a little type to hold the location of the certs, made a function to test for if I am on live server or not, import the certificate location into the previous made type if on the server, and then finally in the API function, serve up over https or http depending on if certificates are found or not.</p> <p>So the implementation itself.</p> <p>In package structs:</p> <pre><code>type TLS_t struct { Fullchain string PrivKey string } </code></pre> <p>In package fileIO:</p> <pre><code>func GetTLSExists() (structs.TLS_t, bool) { var fullchain = &#34;/etc/letsencrypt/live/katzrule.com/fullchain.pem&#34; var privKey = &#34;/etc/letsencrypt/live/katzrule.com/privkey.pem&#34; var TLS structs.TLS_t var exists bool if _, err := os.Stat(&#34;./conf/app.ini&#34;); err != nil { exists = false } else { exists = true TLS.Fullchain = fullchain TLS.PrivKey = privKey } return TLS, exists } </code></pre> <p>The file I check for - &#39;./conf/app.ini&#39; only exist on my server. You can check for any file you wish that you know only exist on the server - or have an initialization file you load on startup, with one field (assuming JSON or XML encoding) saying if on live or dev. Anyway, this little hack works for me.</p> <p>Finally in my API package:</p> <pre><code>func Initialize() { router := mux.NewRouter() ip, err := fileIO.GetPrivateIP() if err != nil { fmt.Println(&#34;Error loading IP config - exiting&#34;) postgres.Close() os.Exit(0) } server := &amp;http.Server{ Handler: router, Addr: ip, WriteTimeout: 10 * time.Second, ReadTimeout: 10 * time.Second, } router.HandleFunc(&#34;/noDogParkPetition&#34;, noDogPark) TLS, live := fileIO.GetTLSExists() if live { fmt.Println(&#34;TLS Certs loaded - running over https&#34;) log.Fatal(server.ListenAndServeTLS(TLS.Fullchain, TLS.PrivKey)) } else { fmt.Println(&#34;No TLS Certs - running over http&#34;) log.Fatal(server.ListenAndServe()) } } </code></pre> <p>And that is about it. Those with keen eyes may notice my call to fileIO.GetPrivateIP() - this is merely a call to load the IP address. For the same reason as mentioned earlier. By loading the IP from file rather than hardcode it, I can move the app freely between dev and live by just uploading the updated binary. On dev, the file just tells the app to serve on localhost, on live it loads up my AWS outward pointing IP and port.</p> <p>Makes deployment super easy. SSH in, close down the app (and do the usual linux/Ubuntu update/upgrade since this is a very good time to do so), use Filezilla to FTP over SSH the new binary, then start it up all good to Go - if you pardon the pun.</p> <p>Happy - and secure - coding! :) </p> <hr/>**评论:**<br/><br/>kjk: <pre><p>You can do it all in Go code, using <a href="https://godoc.org/golang.org/x/crypto/acme/autocert" rel="nofollow">https://godoc.org/golang.org/x/crypto/acme/autocert</a> library.</p> <p>See <a href="https://blog.kowalczyk.info/article/Jl3G/https-for-free-in-go-with-little-help-of-lets-encrypt.html" rel="nofollow">https://blog.kowalczyk.info/article/Jl3G/https-for-free-in-go-with-little-help-of-lets-encrypt.html</a> for a full explanation</p></pre>Zy14rk: <pre><p>Excellent - even better :)</p> <p>Think I&#39;ll use the example in that blog as a template for my next little backend. Thanks.</p></pre>tialaramex: <pre><p>&#34;as these servers can easily be used for various nefarious purposes&#34;</p> <p>The concern for such AWS hostnames isn&#39;t about nefarious purposes but the fact that the certificates last 90 days while those names are extremely transient, AWS doesn&#39;t even promise they&#39;ll point to the same customer for hours, let alone days. So the problem is that the certificates would too often be misleading.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

788 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传