git ssh https 踩坑记 —- 域账号密码更新

前几天突然通知要更新公司的域账号密码,然后git pull就一直报

fatal: Authentication failed for ‘https://git ...

很奇怪的是,有一个项目git pull push都是好的。

上网查了下用以下命令可以看到

git remote get-url origin

好的项目是用了ssh,不好的项目用的是https,https把旧的密码存到电脑里了,所以一直登陆不上

解决方法1–修改密码:

// 清除账户密码缓存
git config --system --unset credential.helper
// 设置账户密码永久保存
git config --global credential.helper store
// 拉代码,重新输入账号密码登陆一次,以后再也不用再输账号密码
git pull

解决方法2–改用ssh方式认证:

// 去除https源
git remote remove origin
// 添加ssh远端源
git remote add origin [email protected]:xxx/xxx.git

ps: 值得注意的是更换origin后,分支要和远端重新关联一下

git branch --set-upstream-to=origin/dev

网站(Nginx)配置 HTTPS 完整过程

配置站点使用 https,并且将 http 重定向至 https。

1. nginx 的 ssl 模块安装

查看 nginx 是否安装 http_ssl_module 模块。

$ /usr/local/nginx/sbin/nginx -V

如果出现 configure arguments: --with-http_ssl_module, 则已安装(下面的步骤可以跳过,进入 nginx.conf 配置)。

下载 nginx 安装包 http://nginx.org/download/nginx-1.14.1.tar.gz

# 下载安装包到 src 目录
$ cd /usr/local/src
$ wget http://nginx.org/download/nginx-1.14.1.tar.gz

解压安装包。

$ tar -zxvf nginx-1.14.1.tar.gz

配置 ssl 模块。

$ cd nginx-1.14.1
$ ./configure --prefix=/usr/local/nginx --with-http_ssl_module

使用 make 命令编译(使用make install会重新安装nginx),此时当前目录会出现 objs 文件夹。

用新的 nginx 文件覆盖当前的 nginx 文件。

$ cp ./objs/nginx /usr/local/nginx/sbin/

再次查看安装的模块(configure arguments: --with-http_ssl_module说明ssl模块已安装)。

$ /usr/local/nginx/sbin/nginx -V

nginx version: nginx/1.14.1
...
configure arguments: --with-http_ssl_module

2. ssl 证书部署

这里使用的是阿里云的免费证书,期限为1年,申请地址https://common-buy.aliyun.com/?spm=5176.2020520154.0.0.45d356a7FlPIts&commodityCode=cas#/buy(如果需要更长时间的或者其他证书可能需要购买,这里提供下阿里的优惠活动购物车优惠卷(https://promotion.aliyun.com/ntms/act/shoppingcart.html?userCode=znftgj11)~)。

  • 下载申请好的 ssl 证书文件压缩包到本地并解压(这里是用的 pem 与 key 文件,文件名可以更改)。
  • 在 nginx 目录新建 cert 文件夹存放证书文件。
$ cd /usr/local/nginx
$ mkdir cert

将这两个文件上传至服务器的 cert 目录里。

这里使用 mac 终端上传至服务器的 scp 命令(这里需要新开一个终端,不要使用连接服务器的窗口):

$ scp /Users/yourname/Downloads/ssl.pem [email protected]:/usr/local/nginx/cert/
$ scp /Users/yourname/Downloads/ssl.key [email protected]:/usr/local/nginx/cert/
scp [本地文件路径,可以直接拖文件至终端里面] [<服务器登录名>@<服务器IP地址>:<服务器上的路径>]

3. nginx.conf 配置

编辑 /usr/local/nginx/conf/nginx.conf 配置文件:

配置 https server。

注释掉之前的 http server 配置,新增 https server:

server {
    # 服务器端口使用443,开启ssl, 这里ssl就是上面安装的ssl模块
    listen       443 ssl;
    # 域名,多个以空格分开
    server_name  baidu.com www.baidu.com;

    # ssl证书地址
    ssl_certificate     /usr/local/nginx/cert/ssl.pem;  # pem文件的路径
    ssl_certificate_key  /usr/local/nginx/cert/ssl.key; # key文件的路径

    # ssl验证相关配置
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    #加密算法
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;    #安全链接可选的加密协议
    ssl_prefer_server_ciphers on;   #使用服务器端的首选算法

    location / {
        root   html;
        index  index.html index.htm;
    }
}

将 http 重定向 https

server {
    listen       80;
    server_name  baidu.com www.baidu.com;
    return 301 https://$server_name$request_uri;
}

4. 重启 nginx

$ /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

如果 80 端口被占用,用kill [id]来结束进程:

# 查看端口使用
$ netstat -lntp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      21307/nginx: master 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3072/sshd           
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      21307/nginx: master 

# 结束 80 端口进程
$ kill 21307

再次重启 nginx :

$ /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

无信息提示就成功啦~

windows下用nginx配置https服务器

1.安装nginx

先到nginx官网下载nginx http://nginx.org/en/download.html

未分类

将下载好的文件解压出来修改文件名为 nginx ,然后拷贝到C盘下,目录如下:

未分类

  • 运行 nginx
start nginx
  • 验证

在浏览器中输入 localhost 访问即可,如出现以下页面,即安装成功

未分类

2.安装 OpenSSL

下载OpenSSL http://slproweb.com/products/Win32OpenSSL.html

未分类

下载完成安装到 C:OpenSSL-Win64

配置环境变量

未分类

在path变量后需要加入 %OPENSSL_HOME%

未分类

3.生成https证书

在C:nginx下创建ssl文件夹 用于存放证书

创建私钥 (建议使用系统窗口,不要用gitBash 有涉及到选择的地方,gitBash无法选择)

openssl genrsa -des3 -out shidian.key 1024 //shidian 自己取的名字

效果如下:

未分类

未分类

创建 csr 证书

openssl req -new -key shidian.key -out shidian.csr

未分类

此时效果:

未分类

删除密码 复制 shidian.key 并重命名 shidian.key.org

openssl rsa -in shidian.key.org -out shidian.key

未分类

生成crt证书

openssl x509 -req -days 365 -in shidian.csr -signkey shidian.key -out shidian.crt

未分类

最后生成证书如下

未分类

4.修改 nginx 下的 nginx.conf配置文件

C:nginxconfnginx.conf
upstream nodejs__upstream2 {
    server 127.0.0.1:8080; # 需要监听的端口名 我用的
    keepalive 64;
}

server {
    listen 443 ssl;
    server_name dev.kt.looklook.cn; # 配置的https的域名

    ssl_certificate      C://nginx//ssl//shidian.crt;  # 这个是证书的crt文件所在目录
    ssl_certificate_key  C://nginx//ssl//shidian.key;  # 这个是证书key文件所在目录

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

 location / {
    proxy_set_header   X-Real-IP            $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header   Host                   $http_host;
    proxy_set_header   X-NginX-Proxy    true;
    proxy_set_header   Connection "";
    proxy_http_version 1.1;
    proxy_pass         http://nodejs__upstream2;
 }
}
  • 重启nginx
nginx -s reload
  • 访问

输入你配置好的域名即可访问了

Centos6.x下设置Apache自建https的证书

第一步 – 安装Mod SSL

为了建立自签名证书,我们首先要确保mod_ssl ,Apache模块,它提供了支持SSL加密,安装在我们的VPS。
我们可以安装mod_ssl与yum命令:

#  sudo yum install mod_ssl

#  sudo vim  /etc/httpd/conf/httpd.conf
LoadModule ssl_module /usr/lib64/httpd/modules/mod_ssl.so

第二步 – 创建新证书

现在Apache已准备好使用加密,我们可以继续生成新的SSL证书。
该证书将存储有关您网站的一些基本信息,并且将伴有允许服务器安全处理加密数据的密钥文件。

首先,我们需要创建一个新目录,我们将存储服务器密钥和证书:

#  sudo mkdir /etc/httpd/ssl

现在,我们必须把我们的文件的位置,我们可以创建一个SSL密钥和证书文件openssl :

#  sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/httpd/ssl/apache.key -out /etc/httpd/ssl/apache.crt

适当填写提示。 最重要的线是要求一个Common Name 。
您需要输入要与服务器关联的域名。 如果您没有域名,可以输入公共IP地址。

第三步 – 设置证书

我们现在拥有完成的接口的所有必需的组件。 接下来要做的是设置虚拟主机以显示新证书。

使用root权限在文本编辑器中打开Apache的SSL配置文件:

# sudo vim /etc/httpd/conf.d/ssl.conf

内容如下:

Listen 443
<VirtualHost *:443>
        DocumentRoot "/www/test"
        ServerName www.test120.com
        #SSL引擎操作开关
        SSLEngine on
        #指定服务器证书位置
        SSLCertificateFile "/etc/httpd/ssl/apache.crt"
        #服务器私钥文件
        SSLCertificateKeyFile "/etc/httpd/ssl/apache.key"
</VirtualHost>
#   sudo  service httpd restart 

最后 ,访问浏览器

https://www.test120.com/

successful

tomcat配置https自签名证书(keytool生成)

生成keystore

keytool -genkeypair -alias "server" -keyalg "RSA" -validity "365" -keystore "/app/webapp/tomcat/https/server.keystore"
[webapp@machina https]$ pwd
/app/webapp/tomcat/https
[webapp@machina https]$ keytool -genkeypair -alias "server" -keyalg "RSA" -validity "365" -keystore "/app/webapp/tomcat/https/server.keystore"
Enter keystore password:  
Re-enter new password: 
What is your first and last name?
  [Unknown]:  10.13.22.102
What is the name of your organizational unit?
  [Unknown]:  ai
What is the name of your organization?
  [Unknown]:  ai
What is the name of your City or Locality?
  [Unknown]:  gz
What is the name of your State or Province?
  [Unknown]:  gd
What is the two-letter country code for this unit?
  [Unknown]:  cn
Is CN=10.13.22.102, OU=ai, O=ai, L=gz, ST=gd, C=cn correct?
  [no]:  yes

Enter key password for <server>
        (RETURN if same as keystore password):  
Re-enter new password: 

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore /app/webapp/tomcat/https/server.keystore -destkeystore /app/webapp/tomcat/https/server.keystore -deststoretype pkcs12".
[webapp@machina https]$ 

修改配置server.xml

[webapp@machina conf]$ pwd
/app/webapp/tomcat/apache-tomcat-7.0.88/conf
[webapp@machina conf]$ vi server.xml
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

改为:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="/app/webapp/tomcat/https/server.keystore" keystorePass="123456"/>

保存:
:wq

修改https的tomcat里的默认端口8443(也可不改,用默认的)。
这里修改为18003。共修改三处。另外两处是注释里的,可不修改。

    <Connector port="18002" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Connector port="18002" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="18003" />

    <Connector port="18003" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="/app/webapp/tomcat/https/server.keystore" keystorePass="123456"/>

    <Connector port="8009" protocol="AJP/1.3" redirectPort="18003" />

修改tomcat的web.xml,强制http跳转到https

[webapp@machina conf]$ pwd
/app/webapp/tomcat/apache-tomcat-7.0.88/conf
[webapp@machina conf]$ vi web.xml

后面加上这样一段:

    <login-config>    
        <!-- Authorization setting for SSL -->    
        <auth-method>CLIENT-CERT</auth-method>    
        <realm-name>Client Cert Users-only Area</realm-name>    
    </login-config>    
    <security-constraint>    
        <!-- Authorization setting for SSL -->    
        <web-resource-collection >    
            <web-resource-name >SSL</web-resource-name>    
            <url-pattern>/*</url-pattern>    
        </web-resource-collection>    
        <user-data-constraint>    
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>    
        </user-data-constraint>    
    </security-constraint>

重启tomcat

[webapp@machina bin]$ pwd
/app/webapp/tomcat/apache-tomcat-7.0.88/bin
[webapp@machina bin]$ sh shutdown.sh
Using CATALINA_BASE:   /app/webapp/tomcat/apache-tomcat-7.0.88
Using CATALINA_HOME:   /app/webapp/tomcat/apache-tomcat-7.0.88
Using CATALINA_TMPDIR: /app/webapp/tomcat/apache-tomcat-7.0.88/temp
Using JRE_HOME:        /opt/jdk1.8.0_151
Using CLASSPATH:       /app/webapp/tomcat/apache-tomcat-7.0.88/bin/bootstrap.jar:/app/webapp/tomcat/apache-tomcat-7.0.88/bin/tomcat-juli.jar
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=256m; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[webapp@machina bin]$ sh startup.sh
Using CATALINA_BASE:   /app/webapp/tomcat/apache-tomcat-7.0.88
Using CATALINA_HOME:   /app/webapp/tomcat/apache-tomcat-7.0.88
Using CATALINA_TMPDIR: /app/webapp/tomcat/apache-tomcat-7.0.88/temp
Using JRE_HOME:        /opt/jdk1.8.0_151
Using CLASSPATH:       /app/webapp/tomcat/apache-tomcat-7.0.88/bin/bootstrap.jar:/app/webapp/tomcat/apache-tomcat-7.0.88/bin/tomcat-juli.jar
Tomcat started.

访问

http://10.13.22.102:18002/ops/app

自动跳转:

https://10.13.22.102:18003/ops/app

让一个端口同时做两件事:http/https和ssh

相信很多人都在YY:能不能让80端口分析连接协议,如果是http协议就让服务器交给http服务程序(如Apache、Nginx等)处理,如果是ssh协议就交给ssh服务程序(如OpenSSH Server)处理呢?

答案显然是有的。

首先,配置http服务程序监听8080端口或者让https服务监听8443端口,配置ssh服务程序监听22端口。具体不再赘述,如果这都不懂就不用往下看了,因为肯定会搞不定的。

然后,安装一个叫haproxy的强大工具。步骤如下。

下载源代码:

wget http://haproxy.1wt.eu/download/1.4/src/haproxy-1.4.16.tar.gz

查看当前内核版本:

uname -r

然后进入目录编译安装:

cd haproxy-1.4.16
make TARGET=linux26 PREFIX=/usr/local/blog.creke.net/haproxy
make install PREFIX=/usr/local/blog.creke.net/haproxy

其中,第二行的“TARGET”参数要和内核版本一致。第二、三行的“PREFIX”是安装位置。

最后,配置haproxy。

如果要监听80端口,检测到http协议就转发给8080端口使用HTTP,否则转发给22端口使用ssh。配置如下:

#By http://blog.creke.net/
global 
    maxconn 5120  
    chroot /usr/local/blog.creke.net/haproxy   
    daemon 
    quiet 
    nbproc 2 
    pidfile /usr/local/blog.creke.net/haproxy/haproxy.pid
defaults 
    timeout connect 5s 
    timeout client 50s 
    timeout server 20s
listen http 
    bind :80 
    timeout client 1h 
    tcp-request inspect-delay 2s 
    acl is_http req_proto_http 
    tcp-request content accept if is_http 
    server server-http :8080 
    use_backend ssh if !is_http
backend ssh 
    mode tcp 
    timeout server 1h 
    server server-ssh :22

如果还有监听443端口,检测到https协议就转发到8443端口使用HTTPS,否则转发给22端口使用ssh。则配置如下:

global 
    maxconn 5120  
    chroot /usr/local/blog.creke.net/haproxy   
    daemon 
    quiet 
    nbproc 2 
    pidfile /usr/local/blog.creke.net/haproxy/haproxy.pid
defaults 
    timeout connect 5s 
    timeout client 50s 
    timeout server 20s
listen https 
    bind :443 
    timeout client 1h 
    tcp-request inspect-delay 2s 
    acl is_ssl req_ssl_ver 2:3.1 
    tcp-request content accept if is_ssl 
    server server-https :8443 
    use_backend ssh if !is_ssl
backend ssh 
    mode tcp 
    timeout server 1h 
    server server-ssh :22

把内容保存为“/usr/local/blog.creke.net/haproxy/etc/haproxy.conf”,执行命令:

/usr/local/blog.creke.net/haproxy/sbin/haproxy -f /usr/local/blog.creke.net/haproxy/etc/haproxy.conf

即可运行。

好了,大家应该可以举一反三,起码也可以依葫芦画瓢吧。

HTTPS服务的Kubernetes ingress配置实践

在公有云被广泛接纳的今天,数据传输安全问题日益凸显,因为在公有云提供商的经典网络(二层互通)中,即便是内部网络通信也要考虑网络嗅探等hack手段,这也是公有云主推所谓“专用网络(二层隔离)”的原因之一。从应用的角度,我们应该尽量通过技术手段保证数据通信的安全性。而目前最常用的方式就是基于SSL/TLS的安全通信方式了,在七层,对应的就是https了。

这样,下面的仅在负载均衡/反向代理入口做加密通信的传统模型越来越无法满足数据安全性的需要了(nginx与backend service之间是基于明文的http通信):

传统安全通信模型:

client --- (via https) ---> nginx ---- (via http) ----> upstream backend services

我们需要下面的模型:

更为安全的通信模型:

client --- (via https) ---> nginx ---- (via https) ----> upstream backend services

在Kubernetes集群中,这种情况稍好些,首先,业务负载运行在集群的“虚拟网络”中,其次,一些K8s的网络插件实现是支持跨节点网络加密的(有一定的网络性能损耗),比如weave。但永远没有绝对的安全,作为业务应用的设计和实现人员,我们要尽可能的保证数据的通信安全,因此在面向七层的应用中,要尽可能的使用基于HTTPS的通信模型。本篇就来实践一下如何为Kubernetes集群内的HTTPS服务进行ingress的配置。

一. 例子概述与环境准备

在《实践kubernetes ingress controller的四个例子》一文中,我讲解了四种基本的kubernetes ingress配置方式。在这些例子中,有些例子的ingress controller(nginx)与backend service之间使用的是https,但client到ingress controller之间的通信却一直是基于http的。在本文中,我们的目标就是上面提到的那个更为安全的通信模型,即client与ingress controller(nginx)、nginx与backend service之间均使用的是https通信。这里在《实践kubernetes ingress controller的四个例子》一文例子的基础上,我们创建一个新的nginx ingress controller: nginx-ingress-controller-ic3,并将后端的svc7~svc9三个不同类型的服务暴露给client,如下图所示:

未分类

  • svc7: 是对传统通信模型的“复现”,即client与ingress controller(nginx)间采用https加密通信,但ingress controller(nginx)与svc7间则是明文的http通信;
  • svc8: 是ssl-termination的安全配置模型,即client与svc8的https通信分为“两段”,client与nginx建立https连接后,nginx将client提交的加密请求解密后,再向svc8发起https请求,并重新加密请求数据。这种client端ssl的过程在反向代理或负载均衡器终结的https通信方式被称为“ssl-termination”。
  • svc9: 是ssl-passthrough的安全配置模型,即nginx不会对client的https request进行解密,而是直接转发给backend的svc9服务,client端的ssl过程不会终结于nginx,而是在svc9对应的pod中终结。这种https通信方式被称为”ssl-passthrough”。这种配置模型尤其适合backend service对client端进行client certificate验证的情况,同时也降低了nginx加解密的性能负担。

本文基于下面环境进行实验:kubernetes 1.10.3、weave networks 2.3.0、nginx-ingress-controller:0.15.0。关于本文涉及的例子的源码、chart包以及ingress controllers的yaml源文件可以在这里下载到。

二. 建立新的ingress-nginx-controller:nginx-ingress-controller-ic3

为了更好地进行例子说明,我们建立一个新的ingress-nginx-controller:nginx-ingress-controller-ic3,svc7~svc9都通过该ingress controller进行服务入口的暴露管理。要创建nginx-ingress-controller-ic3,我们首先需要在ic-common.yaml中为Role: nginx-ingress-role添加一个resourceName: “ingress-controller-leader-ic3″,并apply生效:

// ic-common.yaml
... ...
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-ic1"
      - "ingress-controller-leader-ic2"
      - "ingress-controller-leader-ic3"
... ...

# kubectl apply -f ic-common.yaml

我们为nginx-ingress-controller-ic3创建nodeport service,新nodeport为:30092:

// ic3-service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-ic3
  namespace: ingress-nginx-demo
spec:
  type: NodePort
  ports:
  - name: https
    port: 443
    targetPort: 443
    nodePort: 30092
    protocol: TCP
  selector:
    app: ingress-nginx-ic3

注意:ingress-nginx-ic3 service的nodeport映射到ic3 ingress controller的443端口,也就是支持安全通信的端口,而不是明文的80端口。

最后创建nginx-ingress-controller-ic3 pod,可以复制一份ic2-mandatory.yaml,然后将内容中的ic2全部修改为ic3即可:

# kubectl apply -f ic3-mandatory.yaml

如无意外,nginx-ingress-controller-ic3应该已经正常地运行在你的k8s cluster中了。

三. svc7: 使用ssl termination,但nginx与backend服务之间采用明文传输(http)

加密Web流量有两个主要配置方案:SSL termination和SSL passthrough。

使用SSL termination时,客户端的SSL请求在负载均衡器/反向代理中解密,解密操作将增加负载均衡器的工作负担,较为耗费CPU,但简化了SSL证书的管理。至于负载均衡器和后端之间的流量是否加密,需要nginx另行配置。

SSL Passthrough,意味着client端将直接将SSL连接发送到后端(backend)。与SSL termination不同,请求始终保持加密,并且解密负载分布在后端服务器上。但是,这种情况的SSL证书管理略复杂,证书必须在每台服务器上自行管理。另外,在这种方式下可能无法添加或修改HTTP header,可能会丢失X-forwarded-* header中包含的客户端的IP地址,端口和其他信息。

我们先来看一种并不那么“安全”的“传统模型”:在nginx上暴露https,但nginx到backend service(svc7)采用http。

我们先来创建相关的密钥和公钥证书,并以一个Secret:ingress-controller-demo-tls-secret存储密钥和证书数据:

// ingress-controller-demo/manifests下面

# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ic3.key -out ic3.crt -subj "/CN=*.tonybai.com/O=tonybai.com"
# kubectl create secret tls ingress-controller-demo-tls-secret --key  ic3.key --cert ic3.crt

svc7几乎是和svc1一样的程序(输出的字符串标识不同),但svc7的ingress与svc1大不相同,因为我们需要通过https访问svc7的ingress:

// svc7的values.yaml
... ...
replicaCount: 1

image:
  repository: bigwhite/ingress-controller-demo-svc7
  tag: v0.1
  pullPolicy: Always

service:
  type: ClusterIP
  port: 443

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: ic3
  path: /
  hosts:
    - svc7.tonybai.com
  tls:
    - secretName: ingress-controller-demo-tls-secret
      hosts:
        - svc7.tonybai.com
... ...

与svc1的values.yaml不同的是,我们使用的ingress controller是ic3,我们开启了tls,secret用的就是我们上面创建的那个secret:ingress-controller-demo-tls-secret。创建ic3-svc7后,我们看到ingress controller内部的nginx.conf中有关svc7的配置输出如下:

# kubectl exec nginx-ingress-controller-ic3-67f7cf7845-2tnc9 -n ingress-nginx-demo -- cat /etc/nginx/nginx.conf

        # map port 442 to 443 for header X-Forwarded-Port
        map $pass_server_port $pass_port {
                442              443;
                default          $pass_server_port;
        }

        upstream default-ic3-svc7-http {
                least_conn;

                keepalive 32;

                server 192.168.28.13:8080 max_fails=0 fail_timeout=0;

        }

## start server svc7.tonybai.com
        server {
                server_name svc7.tonybai.com ;

                listen 80;

                listen [::]:80;

                set $proxy_upstream_name "-";

                listen 442 proxy_protocol   ssl http2;

                listen [::]:442 proxy_protocol  ssl http2;

                # PEM sha: 248951b75535e0824c1a7f74dc382be3447057b7
                ssl_certificate                         /ingress-controller/ssl/default-ingress-controller-demo-tls-secret.pem;
                ssl_certificate_key                     /ingress-controller/ssl/default-ingress-controller-demo-tls-secret.pem;

                ssl_trusted_certificate                 /ingress-controller/ssl/default-ingress-controller-demo-tls-secret-full-chain.pem;
                ssl_stapling                            on;
                ssl_stapling_verify                     on;

                location / {
                        ... ...
                        proxy_pass http://default-ic3-svc7-http;

                        proxy_redirect                          off;

                }
           ... ...
        }
        ## end server svc7.tonybai.com

可以看到30092(nodeport) 映射的ingress controller的443端口在svc7.tonybai.com这个server域名下已经有了ssl标识,并且ssl_certificate和ssl_certificate_key对应的值就是我们之前创建的ingress-controller-demo-tls-secret。

我们通过curl访问以下svc7服务:

# curl -k https://svc7.tonybai.com:30092
Hello, I am svc7 for ingress-controller demo!

此时,如果再用http方式去访问svc7,你会得到下面错误结果:

# curl http://svc7.tonybai.com:30092
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.13.12</center>
</body>
</html>

四. svc8: 使用ssl termination,但nginx与backend服务之间采用加密传输(https)

前面说过,SSL termination配置场景中,负载均衡器和后端之间的流量是否加密,需要nginx另行配置。svc7采用了未加密的方式,nginx -> backend service存在安全风险,我们要将其改造为也通过https进行数据加密传输,于是有了svc8这个例子。

svc8对应的程序本身其实是上一篇文章《实践kubernetes ingress controller的四个例子》中的svc2的clone(唯一修改就是输出的log中的标识)。

在svc8对应的chart中,我们将values.yaml改为:

// ingress-controller-demo/charts/svc8/values.yaml

replicaCount: 1

image:
  repository: bigwhite/ingress-controller-demo-svc8
  tag: v0.1
  pullPolicy: Always

service:
  type: ClusterIP
  port: 443

ingress:
  enabled: true
  annotations:
    # kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/secure-backends: "true"
    kubernetes.io/ingress.class: ic3
  path: /
  hosts:
    - svc8.tonybai.com
  tls:
    - secretName: ingress-controller-demo-tls-secret
      hosts:
        - svc8.tonybai.com

... ...

与svc7不同点在于values.yaml中的新annotation: nginx.ingress.kubernetes.io/secure-backends: “true”。这个annotation让nginx以https的方式去访问backend service: svc8。安装svc8 chart后,ingress nginx controller为svc8生成的配置如下:

## start server svc8.tonybai.com
        server {
                server_name svc8.tonybai.com ;

                listen 80;

                listen [::]:80;

                set $proxy_upstream_name "-";

                listen 442 proxy_protocol   ssl http2;

                listen [::]:442 proxy_protocol  ssl http2;

                # PEM sha: 248951b75535e0824c1a7f74dc382be3447057b7
                ssl_certificate                         /ingress-controller/ssl/default-ingress-controller-demo-tls-secret.pem;
                ssl_certificate_key                     /ingress-controller/ssl/default-ingress-controller-demo-tls-secret.pem;

                ssl_trusted_certificate                 /ingress-controller/ssl/default-ingress-controller-demo-tls-secret-full-chain.pem;
                ssl_stapling                            on;
                ssl_stapling_verify                     on;

                location / {
                     ... ...
                        proxy_pass https://default-ic3-svc8-https;

                        proxy_redirect                          off;

                }

        }
        ## end server svc8.tonybai.com

        upstream default-ic3-svc8-https {
                least_conn;

                keepalive 32;

                server 192.168.28.14:8080 max_fails=0 fail_timeout=0;

        }

使用curl访问svc8服务(-k: 忽略对server端证书的校验):

# curl -k https://svc8.tonybai.com:30092
Hello, I am svc8 for ingress-controller demo!

五. svc9: 使用ssl passthrough, termination at pod

某些服务需要通过对client端的证书进行校验的方式,进行身份验证和授权,svc9就是这样一个对client certification进行校验的双向https校验的service。针对这种情况,ssl termination的配置方法无法满足需求,我们需要使用ssl passthrough的方案。

在ingress nginx controller开启ssl passthrough方案需要在ingress controller和ingress中都做一些改动。

首先我们需要为nginx-ingress-controller-ic3添加一个新的命令行参数:–enable-ssl-passthrough,并重新apply生效:

// ic3-mandatory.yaml
... ...
spec:
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller-ic3
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0
          args:
            - /nginx-ingress-controller
            - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
            - --configmap=$(POD_NAMESPACE)/nginx-configuration-ic3
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services-ic3
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services-ic3
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx-ic3
            - --annotations-prefix=nginx.ingress.kubernetes.io
            - --enable-ssl-passthrough
            - --ingress-class=ic3
... ...

然后在svc9的chart中,为ingress添加新的annotation
nginx.ingress.kubernetes.io/ssl-passthrough: “true”

// ingress-controller-demo/charts/svc9/values.yaml

replicaCount: 1

image:
  repository: bigwhite/ingress-controller-demo-svc9
  tag: v0.1
  pullPolicy: Always

service:
  type: ClusterIP
  port: 443

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: ic3
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"

  path: /
  hosts:
    - svc9.tonybai.com
  tls:
    - secretName: ingress-controller-demo-tls-secret
      hosts:
        - svc9.tonybai.com
... ...

isntall svc9 chart之后,我们用curl来访问以下svc9:

# curl -k  https://svc9.tonybai.com:30092
curl: (35) gnutls_handshake() failed: Certificate is bad

由于svc9程序对client端的certificate进行验证,没有提供client certificate的curl请求被拒绝了!svc9 pod的日志也证实了这一点:

2018/06/25 05:36:29 http: TLS handshake error from 192.168.31.10:38634: tls: client didn't provide a certificate

我们进入到ingress-controller-demo/src/svc9/client路径下,执行:

# curl -k --key ./client.key --cert ./client.crt https://svc9.tonybai.com:30092
Hello, I am svc9 for ingress-controller demo!

带上client.crt后,svc9通过了验证,返回了正确的应答。

client路径下是一个svc9专用的客户端,我们也可以执行该程序去访问svc9:

# go run client.go
Hello, I am svc9 for ingress-controller demo!

我们再看看采用ssl-passthrough方式下ingress-nginx controller的访问日志,当curl请求发出时,ingress-nginx controller并未有日志输出,因为没有在nginx处ssl termnination,从此也可以证实:nginx将client的ssl过程转发到pod中去了,即passthrough了。

51短信平台:企业级短信平台定制开发专家 https://51smspush.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

nginx配置https的部署实践

http以明文的形式在浏览器和服务器之间交换数据,没有任何数据加密,攻击者可以在截取之间的信息并读懂,这明显不安全,所以现在浏览器浏览器都要求网站域名配置SSL域名证书,以https协议传输内容。

那问题来了:

未分类

HTTP与HTTPS

  • HTTP:超文本传输协议
  • HTTPS:超文本传输安全协议

简单来说,可以用这个公式:HTTPS = HTTP + SSL

  • SSL:安全套接层,一种安全协议

也就是说:

为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

未分类


未分类

申请ssl域名证书

登录腾讯云之后,找到SSL证书管理栏目,购买或者申请域名证书。

注意:

  • 免费证书有效期是一年,一年后手动重新申请即可
  • 域名需要备案

未分类

申请完了之后,就可以下载证书啦~

未分类

如图下载的域名证书,可以配置到Apache、Nginx、Tomcat等服务器上面。

未分类

nginx配置https步骤

好,接下来我们进入正题,给nginx配置域名证书嘿~

解压下载下来的域名证书,获取Nginx里面的两个文件。

未分类

  • crt文件是以PEM格式存在的证书,可以用于不同的程序和设备
  • key文件是授权文件

第一步

把crt和key文件上传到nginx的conf目录下。

未分类

第二步

nginx.conf或自定义配置文件上配置SSL证书。

未分类

HTTPS的默认端口是443,就像HTTP的默认端口80一样,从图中可以看到,这个服务最后代理的是8080端口的tomcat。

第三步

配置完了第二步已经完成一大半了,只要用户输入https://www.java-mindmap.com就可以访问我的社区网站,但是一般用户都懒得输入https://,而不输入的话默认就是发起http链接,所以,需要还需要配置http强制转换成https的链接。

未分类

这样,当用户访问http链接时候,强制转成了https的服务了。

未分类

至此,HTTPS配置成功~

未分类

Ubuntu Docker 配置 Tomcat 和 Nginx 使用 HTTPS 访问

安装 Docker

使用脚本自动安装

curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

更改镜像地址

  • 修改或新建 /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}

启动 Docker

sudo systemctl daemon-reload
sudo systemctl enable docker
sudo systemctl start docker

配置 Tomcat

启动 Tomcat 容器

docker pull tomcat
docker run --name tomcat -d -p 8080:8080 tomcat

修改 Tomcat Manager 应用

docker exec -it tomcat /bin/bash
  • 修改 webapps/manager/META-INF/content.xml,允许需要的IP访问,这里运行所有的IP访问
<Context antiResourceLocking="false" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="^.*$" />
  <Manager sessionAttributeValueClassNameFilter="java.lang.(?:Boolean|Integer|Long|Number|String)|org.apache.catalina.filters.CsrfPreventionFilter$LruCache(?:$1)?|java.util.(?:Linked)?HashMap"/>
</Context>

配置 Tomcat 用户

  • 修改 conf/tomcat-user.xml,添加用户
<role rolename="admin-gui"/>
<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>

配置 Nginx

配置目录

  • 新建目录 /home/ubuntu/hellowood/dev/nginx/conf, /home/ubuntu/hellowood/dev/nginx/log, /home/ubuntu/hellowood/dev/nginx/certs
  • 下载并解压相应的Nginx证书文件到 /home/ubuntu/hellowood/dev/nginx/conf

添加 Nginx 配置

  • nginx.conf
server {
      listen 80;
      listen 443 ssl;
      server_name hellowood.com.cn;
      ssl_certificate /etc/nginx/certs/hellowood.com.cn_bundle.crt;
      ssl_certificate_key /etc/nginx/certs/hellowood.com.cn.key;
      location / {
        proxy_pass http://tomcat:8080;
      }
}

http://tomcat:8080: 将所有请求都转发到 tomcat 容器的 8080端口

启动 Nginx 容器

docker pull nginx 
docker run --name nginx -d -p 80:80 -p 443:443 
  --link tomcat:tomcat 
  -v /home/ubuntu/hellowood/dev/nginx/conf:/etc/nginx/conf.d  
  -v /home/ubuntu/hellowood/dev/nginx/log:/var/log/nginx  
  -v /home/ubuntu/hellowood/dev/nginx/certs:/etc/nginx/certs nginx

此时,访问相应的域名:http://hellowood.com.cn和https://hellowood.com.cn会显示Tomcat 的首页,配置完成

记Apache httpd 2.4.6 升级部署 https

一个2014年初上线的项目,要升级https,记录一下。

一共有三台WEB服务器,进入 apache/modules 查看是否有 mod_ssl.so。

两台服务器正常,一台缺失,于是需要动态编译。

官网下载httpd2.4.6(这里需要./httpd -v 查看一下当前版本号),解压缩,进入源码 /modules/ssl/ 目录

cd /usr/local/src/httpd-2.4.6/modules/ssl/

然后执行下面的动态编译命令

当前apahce的路径/bin/apxs -i -c -a -D HAVE_OPENSSL=1 -I /usr/include/openssl -lcrypto -lssl -ldl *.c

此处遇到了第一个坑:报错 /usr/bin/ld: cannot find -lcrypto

搜素一番后,是 /usr/lib64/libssl.so/usr/lib64/libcrypto.so 没有建立软连接。但是搜索出来的解决方案的路径不对,于是参考另外两台服务器

ln -s /lib64/libssl.so.0.9.8e /usr/lib64/libssl.so
ln -s /lib64/libcrypto.so.0.9.8e /usr/lib64/libcrypto.so

使用上面方式建立软链接。

然后再次编译,提示成功了。

但是在httpd restart的时候碰到了第二个坑。

再次报错:mod_ssl.so: undefined symbol: SSL_get_srp_userinfo

搜索一番了解到是 openssl 版本太高。

这才想起来,之前我更新过一次openssl,现在的版本不是 0.9.8e了。

于是 找到现在的openssl对应lib目录 /usr/local/ssl/lib/libcrypto.so.1.0.0

删除现有的链接,重新链接为新的。

rm -rf /usr/lib64/libssl.so
rm -rf usr/lib64/libcrypto.so
ln -s /usr/local/ssl/lib/libssl.so.1.0.0 /usr/lib64/libssl.so
ln -s /usr/local/ssl/lib/libcrypto.so.1.0.0 /usr/lib64/libcrypto.so

于是重新编译apahce,再次重启能够成功了。

在配置https配置文件的过程中,记得要监听443端口并且设置好防火墙规则。

Listen 0.0.0.0:443
Listen [::]:443

其他的配置文件就按照网上的参考就行了。