FAQs: ssh

§解决ssh登录后闲置时间过长而断开连接

通过终端连接服务器时,当鼠标和键盘长时间不操作,服务器就会自动断开连接,解决此问题的方法如下:

  • 方法一、 修改/etc/ssh/sshd_config配置文件,找到ClientAliveCountMax(单位为分钟)修改你想要的值, 执行service sshd reload

  • 方法二、 找到所在用户的.ssh目录,如root用户该目录在:/root/.ssh/ 在该目录创建config文件

$ vi /root/.ssh/config

加入下面一句:

ServerAliveInterval 60

保存退出,重新开启root用户的shell,则ssh远程服务器的时候, 不会因为长时间操作断开。应该是加入这句之后,ssh客户端会每隔一 段时间自动与ssh服务器通信一次,所以长时间操作不会断开。

  • 方法三、 修改/etc/profile配置文件
$ vi /etc/profile

增加:TMOUT=1800 这样30分钟没操作就自动LOGOUT

sshuttle:不需配置的 VPN

sshuttle 被其作者称为 “穷人的 VPN”(A poor man’s instant VPN),甚至不需要远端服务器的 root 权限就可以用(只需要一个普通 SSH 帐号),和在 Mac/Linux 客户端直接用 ssh -D 的方式有点类似。如果不想花钱买 VPN,又懒得自己在 VPS 上安装和设置复杂的 VPN 服务,又不想用 ssh -D 这么朴素的技巧的话可以试一下这个 sshuttle,按照作者的说法 sshuttle 比 sshd -D 的方式快一点,因为 It’s just data-over-TCP,而不是 TCP-over-TCP,TCP-over-TCP 的方式会带来不必要的性能问题,因为 TCP 本身就是可靠传输协议,保证了包的有序性和无差错,并确保包被接受,如果有包丢失的话 TCP 协议可以自己立即重传弥补,所以没必要两层都 TCP,一层 TCP 就比较安全了。

sshuttle 的用法很简单,在客户端下载和运行就可以了(需要有 Python 的支持),无需在服务器端做任何配置(但是需要一个 ssh 帐号和 Python 支持):

$ git clone https://github.com/sshuttle/sshuttle
$ cd sshuttle
$ sudo ./setup.py install
$ sshuttle -r username@sshserver 0.0.0.0/0 -vv
Starting sshuttle proxy.
[local sudo] Password: 
firewall manager: Starting firewall with Python version 2.7.15
firewall manager: ready method name nat.
IPv6 enabled: False
UDP enabled: False
DNS enabled: False
User enabled: False
Binding redirector: 12300 12299
TCP redirector listening on ('127.0.0.1', 12299).
TCP redirector listening with <socket._socketobject object at 0x7f5eb68b1c90>.
Starting client with Python version 2.7.15
c : connecting to server...
...

AppArmor的前世今生和基本使用

一:MAC和DAC (一些前置知识)

DAC(Discretionary Access Control),自主访问控制,是最常用的一类访问控制机制,意思为主体(文件所有者)可以自主指定系统中其它用户对其文件的所有权,最典型的就是Linux的"拥有者/同组用户/其他"。这种方式虽然为用户提供了很大的灵活性,但是缺乏必要的安全性

MAC(Mandatory Access Control),强制访问控制,在这种机制下,系统中的每一个进程,每一个文件,每一个IPC主体都被管理员按照严格的规则设置了相应的安全属性,不能被用户和其它直接或间接的修改。

二:AppArmor

由于SELinux使用复杂,适用于对安全要求特别高的企业或者组织,为了简化操作,就推出了AppArmor,所以可以说AppArmor脱胎于SELinux,但与SELinux基于角色的MAC不同的是,AppArmor是与程序绑定的基于路径的MAC,也就是说如果路径发生改变,策略就会失效。一般的Linux的系统,都会内置以上两种MAC其中的一种,这也意味着,你需要对文件(其它)进行操作,你需要同时通过DAC和 MAC的检测。

AppArmor有两种工作模式:enforcement、complain/learning

  • Enforcement – 在这种模式下,配置文件里列出的限制条件都会得到执行,并且对于违反这些限制条件的程序会进行日志记录。

  • Complain – 在这种模式下,配置文件里的限制条件不会得到执行,AppArmor只是对程序的行为进行记录。例如程序可以写一个在配置文件里注明只读的文件,但AppArmor不会对程序的行为进行限制,只是进行记录。这种模式也叫学习模式,如果某个程序的行为不符合其配置文件的限制,可以将其行为记录到系统日志,并且可以根据程序的行为,将日志转换成配置文件。

AppArmor可以对程序进行多方面的限制,详细可以看官方文档,这里只提供几个基本的例子:

  1. 文件系统的访问控制 例: /home/Desktop/a.c rw 表示程序可以对/home/Desktop/a.c 进行读和写。
  2. 资源限制 例: set rlimit as<=1M ,表示该程序可以使用的虚拟内存小于等于1M
  3. 访问网络 例: network inet tcp ,表示该程序可以在IPV4的情况下使用TCP协议  
  4. capability条目 例:capability setgid,表示程序进行setgid操作。

Athens:香港服务器Docker部署

源起

go1.11开始加入module功能支持GOPROXY,解决go依赖包下载问题(你懂的!),Athens应运而生。

官网介绍:

Athens is a project building on top of vgo (or go1.11+) trying to bring dependencies closer to you so you can count on repeatable builds even at a time when VCS is down.

The big goal of Athens is to provide a new place where dependencies — not code — live. Dependencies are immutable blobs of code and associated metadata that come from Github. They live in storage that Athens controls.

Docker部署

使用Docker进行部署,官方镜像[gomods/proxy:latest](https://hub.docker.com/r/gomods/proxy/ ‘Athens’s docker image’)

$ docker volume create data-athens
$ docker run -d --name athens-proxy --restart always -p 3000:3000 \
    -v data-athens:/var/lib/athens \
    -e ATHENS_DISK_STORAGE_ROOT=/var/lib/athens \ 
    -e ATHENS_STORAGE_TYPE=disk \
    gomods/proxy:latest

Hello, Rustacean

fn main() {
   let greetings = ["Hello", "Hola", "Bonjour",
                    "Ciao", "こんにちは", "안녕하세요",
                    "Cześć", "Olá", "Здравствуйте",
                    "Chào bạn", "您好", "Hallo",
                    "Hej", "Ahoj", "سلام","สวัสดี"];

   for (num, greeting) in greetings.iter().enumerate() {
       print!("{} : ", greeting);
       match num {
           0 =>  println!("This code is editable and runnable!"),
           1 =>  println!("¡Este código es editable y ejecutable!"),
           2 =>  println!("Ce code est modifiable et exécutable !"),
           3 =>  println!("Questo codice è modificabile ed eseguibile!"),
           4 =>  println!("このコードは編集して実行出来ます!"),
           5 =>  println!("여기에서 코드를 수정하고 실행할 수 있습니다!"),
           6 =>  println!("Ten kod można edytować oraz uruchomić!"),
           7 =>  println!("Este código é editável e executável!"),
           8 =>  println!("Этот код можно отредактировать и запустить!"),
           9 =>  println!("Bạn có thể edit và run code trực tiếp!"),
           10 => println!("这段代码是可以编辑并且能够运行的!"),
           11 => println!("Dieser Code kann bearbeitet und ausgeführt werden!"),
           12 => println!("Den här koden kan redigeras och köras!"),
           13 => println!("Tento kód můžete upravit a spustit"),
           14 => println!("این کد قابلیت ویرایش و اجرا دارد!"),
           15 => println!("โค้ดนี้สามารถแก้ไขได้และรันได้"),
           _ =>  {},
       }
   }
}

没错,今天开始,正式入坑Rust,我要成为Rustacean(Rust社区的成员被称为 Rustacean)的一员!我已经是一名Gopher(Golang程序猿的昵称),日常就是使用Go写写bug,研究一下大佬们的代码,然后继续写自个儿的bug,标准的Gopher节奏,WTF~

话说,Golang的吉祥物是Gopher(囊地鼠),陆上跑地欢;Rust的吉祥物是Crab(螃蟹),海里游地慌;巧合吗,很有意思!既如此,已经入坑了陆上跑地欢的Go,再入手个海里游地慌的Rust,又有何妨,乐哉!似乎还有一个Swift,吉祥物是天上飞的雨燕, 也是计划入手的一门语言,但不是现在(项目暂时没用上,不急), 到时候就海陆空全齐了, 哈哈哈~

欲攻其事,必先善其器,各门语言有他们擅长的使用场景,都有他们各自溜的舞台,项目需要或适合什么语言去构建,自然就要入手去使用,达到最好运行效果! 学过很多语言,但日常编程用的最多的还是Go和Java, 嗯哼, 之所以还入手Rust语言,除了项目用的上,更简单的原因就是:看上了TiKV ~So Easy To Nice~

SRE:3节点部署TiKV用于测试功能

源起

闲置几台屌丝版腾讯云服务器(2 core CPU 4GB Memory 40GB Disk),难得清闲,用其中的3台部署一套TiKV用于测试功能和代码研究。

节点分布

使用Docker进行部署,官方镜像pingcap/pd:v2.0.6、pingcap/tikv:v2.0.6

|    Name   |   Host IP   |  Services  |  Docker Volume  |  Data Path  |
| Node1(TB) | 172.22.0.6  |    PD1     |     pd-data     |    /data    |
| Node2(TD) | 172.22.0.10 |    PD2     |     pd-data     |    /data    |
| Node3(TE) | 172.22.0.15 |    PD3     |     pd-data     |    /data    |
| Node1(TB) | 172.22.0.6  |   TiKV1    |     tikv-data   |    /data    |
| Node2(TD) | 172.22.0.10 |   TiKV2    |     tikv-data   |    /data    |
| Node3(TE) | 172.22.0.15 |   TiKV3    |     tikv-data   |    /data    |

Go modules

§Definition

A module is a collection of related go packages. Modules are the unit of source code interchange and versionning.

§Quick history

  • Go before 1.5: populating GOPATH with go get.
  • Go 1.5 and after: dependency vendoring is introduced.
  • vgo is proposed as a prototype for Go modules support.
  • Go 1.11 (beta): vgo is being merged and refined as go mod (experimental).

§Terminology

This article refers to recurrent expressions. Let’s clarify them:

  • “Module root”: the directory containing the file named go.mod.
  • “Module path”: the import path prefix corresponding to the module root.
  • “Main module”: the module containing the directory where the go command is run.

§Module structure

A module is a tree of Go source files to which is added a file named go.mod. It contains the module import name, and the declaration of dependency requirements, exclusions and replacements. Its content would look like this:

module my/thing
  
require (
        one/thing v1.3.2
        other/thing v2.5.0 // indirect
        ...
)

exclude (
        bad/thing v0.7.3
)

replace (
        src/thing 1.0.2 => dst/thing v1.1.0
)

Guide: gorilla/mux

The name mux stands for “HTTP request multiplexer”. Like the standard http.ServeMux, mux.Router matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are:

* Requests can be matched based on URL host, path, path prefix, schemes,
  header and query values, HTTP methods or using custom matchers.
* URL hosts, paths and query values can have variables with an optional
  regular expression.
* Registered URLs can be built, or "reversed", which helps maintaining
  references to resources.
* Routes can be used as subrouters: nested routes are only tested if the
  parent route matches. This is useful to define groups of routes that
  share common conditions like a host, a path prefix or other repeated
  attributes. As a bonus, this optimizes request matching.
* It implements the http.Handler interface so it is compatible with the
  standard http.ServeMux.

Let’s start registering a couple of URL paths and handlers:

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/", HomeHandler)
  r.HandleFunc("/products", ProductsHandler)
  r.HandleFunc("/articles", ArticlesHandler)
  http.Handle("/", r)
  log.Fatal(http.ListenAndServe(":12345", nil))
}

Docker: 对Docker Remote API进行认证

  • 建立证书授权中心
$ sudo mkdir /etc/docker
$ cd /etc/docker
$ echo 01 | sudo tee ca.csl
$ sudo openssl genrsa -des3 -out ca-key.pem
$ sudo openssl req -new -x509 -days 365 -key ca-key.pem -out ca.pem
  • 创建服务器的证书签名请求和密钥
$ sudo openssl genrsa -des3 -out server-key.pem
$ sudo openssl req -new -key server-key.pem -out server.csr
$ sudo openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem
$ sudo openssl rsa -in server-key.pem -out server-key.pem
$ sudo chmod 0600 /etc/docker/server-key.pem /etc/docker/server-cert.pem /etc/docker/ca-key.pem /etc/docker/ca.pem
  • 配置Docker守护进程 (/etc/docker/daemon.json on Linux systems, or C:\ProgramData\docker\config\daemon.json on Windows.)
{
  "debug": true,
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "hosts": ["tcp://<config of CN>:2376"]
}