使用nginx的http验证功能对elasticsearch加密

本文介绍如何利用Nginx进行Elasticsearch的服务管理,包括连接持久化、负载均衡、用户认证及权限控制等内容。
 
 

前言

这篇文章是https://www.elastic.co/blog/playing-http-tricks-nginx的部分翻译,对像我这样的小白学习nginx和elasticsearch有些许帮助,ps:翻译好难。。。e文好的同学还是去看原文吧。。。

正文

Elasticsearch默认是完全暴露在互联网上的RESTful服务接口。 这样做的好处是:web开发人员可以很快熟悉它的API,很容易使用curl命令或者浏览器来查询数据。也非常容易使用各种编程语言封装对应的接口。 Elasticsearch的RESTful接口是基于http开发的,所以它与现有的网络架构兼容性很好。

使用RESTful作为软件架构

现在很多软件使用RESTful服务作为基础架构,这样做的一大好处是你可以很容易插入新功能和修改已有功能。

Nginx

Nginx是一个高性能的反向代理服务。许多大型PHP项目也会使用nginx为静态文件加速。这篇文章使用基础的nginx配置为elasticsearch加上验证和授权功能。 运行Nginx为Elasticsearch做一个端口映射,我们可以非常简单的这样配置:

http {
  server {
    listen 8080;
    location / {
      proxy_pass http://localhost:9200;
    }
  }
}

当访问http://localhost:8080的时候,相当于访问http://localhost:9200
这种配置当然没什么大用,聪明的读者会发现了nginx其实已经做了些工作,比如记录了每次请求的日志。

连接持久化

使用nginx保持elasticsearch连接。这么做可以减少elasticsearch因每次请求都需要连接~断开的压力,节省资源。
更多配置请参考https://gist.github.com/karmi/b0a9b4c111ed3023a52d

events {
    worker_connections  1024;
}

http {

  upstream elasticsearch {
    server 127.0.0.1:9200;

    keepalive 15;
  }

  server {
    listen 8080;

    location / {
      proxy_pass http://elasticsearch;
      proxy_http_version 1.1;
      proxy_set_header Connection "Keep-Alive";
      proxy_set_header Proxy-Connection "Keep-Alive";
    }

  }

}

启动nginx

$ nginx -p $PWD/nginx/ -c $PWD/nginx_keep_alive.conf

没有持久化连接的时候,每次请求elasticsearch数据opened connections都会增加:

$ curl 'localhost:9200/_nodes/stats/http?pretty' | grep total_opened
# "total_opened" : 13
$ curl 'localhost:9200/_nodes/stats/http?pretty' | grep total_opened
# "total_opened" : 14
# ...

使用nginx持久化连接后,opened connections每回都一样:

$ curl 'localhost:8080/_nodes/stats/http?pretty' | grep total_opened
# "total_opened" : 15
$ curl 'localhost:9200/_nodes/stats/http?pretty' | grep total_opened
# "total_opened" : 15
# ...

简单的负载均衡

对这个配置做一个非常小的改动,我们就可以分配requests到不同的elasticsearch节点上:

events {
    worker_connections  1024;
}

http {

  upstream elasticsearch {
    server 127.0.0.1:9200;
    server 127.0.0.1:9201;
    server 127.0.0.1:9202;

    keepalive 15;
  }

  server {
    listen 8080;

    location / {
      proxy_pass http://elasticsearch;
      proxy_http_version 1.1;
      proxy_set_header Connection "Keep-Alive";
      proxy_set_header Proxy-Connection "Keep-Alive";
    }

  }

}

这里我们添加了两个节点在upstream中。Nginx会自动分配(轮询)request到不同的节点中。

$ curl localhost:8080 | grep name
# "name" : "Silver Fox",
$ curl localhost:8080 | grep name
# "name" : "G-Force",
$ curl localhost:8080 | grep name
# "name" : "Helleyes",
$ curl localhost:8080 | grep name
# "name" : "Silver Fox",
# ...

这么做可以将请求分散给所有节点,增加节点只需在upstream中增加url,然后重启nginx
关于更高级的负载均衡功能,请参考Load Balancing with NGINX and NGINX Plus
(注意,elasticsearch本身有负载均衡机制。)

基本的用户认证

默认情况下,elasticsearch不采取认证机制,因为它不是设计在开放的网络环境当中,当你打开9200端口,你的数据,集群都不是安全的。
通常保护elasticsearch集群是通过VPN,防火墙等手段限制。但是如果你希望在外网连接elasticsearch集群,就只能通过用户密码来加以认证了。
可以使用nginx来实现用户认证:

events {
  worker_connections  1024;
}

http {

  upstream elasticsearch {
    server 127.0.0.1:9200;
  }

  server {
    listen 8080;

    auth_basic "Protected Elasticsearch";
    auth_basic_user_file passwords;

    location / {
      proxy_pass http://elasticsearch;
      proxy_redirect off;
    }
  }

}

可以使用很多工具来生成密码,这里使用openssl:

$ printf "john:$(openssl passwd -crypt s3cr3t)\n" > passwords

运行nginx:

$ nginx -p $PWD/nginx/ -c $PWD/nginx_http_auth_basic.conf

普通请求会被拒绝:

$ curl -i localhost:8080
# HTTP/1.1 401 Unauthorized
# ...

输入帐号密码后,就可以建立连接了:

$ curl -i john:s3cr3t@localhost:8080
# HTTP/1.1 200 OK
# ...

现在可以关闭9200端口,只留8080端口对外开放了,想要连接集群必须得通过验证。

简单授权

如果没有授权机制,只要登录,就可以对集群中任何事情,更改或删除数据,查看内部数据,甚至关闭集群。
通过非常小的改动,我们就可以拒绝通过RESTful命令关闭集群。

location / {
  if ($request_filename ~ _shutdown) {
    return 403;
    break;
  }

  proxy_pass http://elasticsearch;
  proxy_redirect off;
}

重启nginx:

$ nginx -p $PWD/nginx/ -c $PWD/nginx_http_auth_deny_path.conf

尝试调用关闭集群,将会返回拒绝信息:

$ curl -i -X POST john:s3cr3t@localhost:8080/_cluster/nodes/_shutdown
# HTTP/1.1 403 Forbidden
# ....

也可以配置允许某些请求,拒绝其余的请求,通过两个location来实现:

events {
  worker_connections  1024;
}

http {

  upstream elasticsearch {
    server 127.0.0.1:9200;
  }

  server {
    listen 8080;

    auth_basic "Protected Elasticsearch";
    auth_basic_user_file passwords;

    location ~* ^(/_cluster|/_nodes) {
      proxy_pass http://elasticsearch;
      proxy_redirect off;
    }

    location / {
      return 403;
      break;
    }
  }

}

这样,请求/_cluster 和 /_nodes将通过,其他的会被拒绝:

$ curl -i john:s3cr3t@localhost:8080/
HTTP/1.1 403 Forbidden
# ...

$ curl -i john:s3cr3t@localhost:8080/_cluster/health
# HTTP/1.1 200 OK
# ...

$ curl -i john:s3cr3t@localhost:8080/_nodes/stats
HTTP/1.1 200 OK
# ...

选择性认证

现在我们想用基本认证保护elasticsearch但是允许ping命令发送HEAD请求到/起到监视集群状态的作用。

events {
  worker_connections  1024;
}

http {

  upstream elasticsearch {
    server 127.0.0.1:9200;
  }

  server {
    listen 8080;

    location / {
      error_page 590 = @elasticsearch;
      error_page 595 = @protected_elasticsearch;

      set $ok 0;

      if ($request_uri ~ ^/$) {
        set $ok "${ok}1";
      }

      if ($request_method = HEAD) {
        set $ok "${ok}2";
      }

      if ($ok = 012) {
        return 590;
      }

      return 595;
    }

    location @elasticsearch {
      proxy_pass http://elasticsearch;
      proxy_redirect off;
    }

    location @protected_elasticsearch {
      auth_basic           "Protected Elasticsearch";
      auth_basic_user_file passwords;

      proxy_pass http://elasticsearch;
      proxy_redirect off;
    }
  }

}

首先,我们定义两个状态代码:590-不需要验证,595-需要验证,使用nginx的location功能,两个location都指向同一个集群,但是其中一个需要认证。
然后我们设置一个变量$ok,默认值0,当进入请求是/,$ok变成01.如果请求是HEAD$ok变成012。
如果$ok是012,返回590状态码,换句话说,不需验证,其他情况返回595,需要验证。

$ curl -i -X HEAD localhost:8080
# HTTP/1.1 200 OK
# ...

$ curl -i localhost:8080
# HTTP/1.1 401 Unauthorized
# ...

$ curl -i john:s3cr3t@localhost:8080
# HTTP/1.1 200 OK
# ...

多角色授权

到这里,我们已经有了一个简单的认证机制。如果我们需要一个更宽泛的认证机制,基于角色的,不如说像下面这样的:

  • 没有认证的用户只能使用ping命令,ping指定的URL(/);
  • 认证过的user用户可以执行_search与_analyze请求;
  • 认证过的admin用户可以执行任何请求。
    我们使用不同的端口为不同的角色服务:
events {
  worker_connections  1024;
}

http {

  upstream elasticsearch {
      server 127.0.0.1:9200;
  }

  # Allow HEAD / for all
  #
  server {
      listen 8080;

      location / {
        return 401;
      }

      location = / {
        if ($request_method !~ "HEAD") {
          return 403;
          break;
        }

        proxy_pass http://elasticsearch;
        proxy_redirect off;
      }
  }

  # Allow access to /_search and /_analyze for authenticated "users"
  #
  server {
      listen 8081;

      auth_basic           "Elasticsearch Users";
      auth_basic_user_file users;

      location / {
        return 403;
      }

      location ~* ^(/_search|/_analyze) {
        proxy_pass http://elasticsearch;
        proxy_redirect off;
      }
  }

  # Allow access to anything for authenticated "admins"
  #
  server {
      listen 8082;

      auth_basic           "Elasticsearch Admins";
      auth_basic_user_file admins;

      location / {
        proxy_pass http://elasticsearch;
        proxy_redirect off;
      }
  }

}

点用openssl命令生成认证文件:

$ printf "user:$(openssl passwd -crypt user)\n"   > users
$ printf "admin:$(openssl passwd -crypt admin)\n" > admins

现在,所有用户都能ping集群,但是做不了其他操作:

$ curl -i -X HEAD localhost:8080
# HTTP/1.1 200 OK
$ curl -i -X GET localhost:8080
# HTTP/1.1 403 Forbidden

user用户可以执行search,analyze请求,其他的不可以:

$ curl -i localhost:8081/_search
# HTTP/1.1 401 Unauthorized
# ...

$ curl -i user:user@localhost:8081/_search
# HTTP/1.1 200 OK
# ...

$ curl -i user:user@localhost:8081/_analyze?text=Test
# HTTP/1.1 200 OK
# ...

$ curl -i user:user@localhost:8081/_cluster/health
# HTTP/1.1 403 Forbidden
# ...

admin用户可以做任何操作:

$ curl -i admin:admin@localhost:8082/_search
# HTTP/1.1 200 OK
# ...

$ curl -i admin:admin@localhost:8082/_cluster/health
# HTTP/1.1 200 OK
# ...

这样轻松解决了基于多角色的授权,这么做的代价是:每一种角色都使用不同的端口。



作者:zhnliving
链接:http://www.jianshu.com/p/7ec26c13abbb
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
<think> 我们正在讨论使用Nginx代理Elasticsearch的方法和配置。根据引用内容,我们可以总结出几种常见的配置场景: 1. 基本代理:将Nginx作为Elasticsearch的反向代理,对外提供服务。 2. 认证代理:当Elasticsearch设置了用户名密码认证时,在Nginx配置中传递认证信息。 3. 路径重写:在代理时可能需要重写路径,例如将某个路径前缀的请求代理到Elasticsearch的根路径。 我们将根据引用中的配置示例,整理出常见的配置步骤和注意事项。 步骤: 1. 安装Nginx(如果未安装)。 2. 修改Nginx配置文件(通常位于`/etc/nginx/nginx.conf`或`/etc/nginx/conf.d/`下的某个文件)。 3. 在配置文件中添加一个`server`块,监听某个端口(如9200),并配置`location`块来代理到Elasticsearch的地址。 配置示例: 场景1:基本代理(无认证) 假设Elasticsearch运行在本地9200端口,我们通过Nginx的9201端口来代理。 ```nginx server { listen 9201; server_name localhost; location / { proxy_pass http://localhost:9200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` 场景2:带基本认证的代理 如果Elasticsearch启用了基础认证(用户名和密码),我们可以在Nginx配置中设置认证头。首先,我们需要将用户名和密码进行Base64编码(注意:这里的Base64编码只是编码,不是加密,因此建议使用HTTPS来保证安全)。 生成Base64编码字符串的方法(在终端执行): ```bash echo -n 'username:password' | base64 ``` 将生成的字符串(如`ZWxhc3RpYzplbGFzdGlj`)配置到`proxy_set_header Authorization`中。 ```nginx server { listen 9201; server_name localhost; location / { proxy_pass http://localhost:9200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 设置认证头 proxy_set_header Authorization "Basic ZWxhc3RpYzplbGFzdGlj"; } } ``` 场景3:路径重写 有时候我们希望将某个路径下的请求代理到Elasticsearch,比如所有以`/es/`开头的请求。同时,我们可能需要去掉这个前缀(重写路径)。 ```nginx server { listen 9201; server_name localhost; location /es/ { # 重写URL:去掉路径中的/es rewrite ^/es/(.*)$ /$1 break; proxy_pass http://localhost:9200; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` 注意:在`proxy_pass`指令中,如果后端地址是以`/`结尾,那么`location`匹配的路径部分会被去除。上面配置中,我们使用了`rewrite`指令来去掉`/es/`前缀。 其他注意事项: 1. 如果Elasticsearch集群有多个节点,可以使用`upstream`模块定义后端服务器组,实现负载均衡。 2. 建议使用HTTPS来保证数据安全,特别是当认证信息在HTTP头中传输时。 3. 配置完成后,使用`nginx -t`测试配置是否正确,然后使用`systemctl restart nginx`(或相应命令)重启Nginx。 示例:使用`upstream`负载均衡 ```nginx upstream elasticsearch_cluster { server 192.168.1.10:9200; server 192.168.1.11:9200; server 192.168.1.12:9200; } server { listen 9201; server_name localhost; location / { proxy_pass http://elasticsearch_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` 以上配置将把请求轮询分发到三个Elasticsearch节点。 引用说明: - 引用[3]提供了一个在Kubernetes中使用ConfigMap配置Nginx代理Elasticsearch的示例,其中包含了基本认证头的设置。 - 引用[4]和[5]分别展示了路径重写和认证代理的配置片段。 因此,根据实际需求选择配置方式。 相关问题: 1. 如何配置Nginx代理ElasticsearchHTTPS访问? 2. 在Nginx代理Elasticsearch时,如何优化性能? 3. 如何通过Nginx代理实现Elasticsearch的访问控制(如IP白名单)? 4. 在Kubernetes中如何部署Nginx代理Elasticsearch? </think>### Nginx代理Elasticsearch配置指南 通过Nginx代理Elasticsearch实现安全访问、负载均衡和路径重写等功能。以下是基于引用内容的详细配置方法: #### 一、基础代理配置(无认证) ```nginx server { listen 9200; location / { proxy_pass http://elasticsearch:9200; # 指向ES集群地址 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; } } ``` **说明**: 1. `listen 9200`:Nginx监听端口(可自定义) 2. `proxy_pass`:目标ES地址(如`http://localhost:9200`或集群地址) 3. `proxy_set_header`:传递客户端真实IP和主机信息[^2][^4] --- #### 二、带身份认证的代理配置 当Elasticsearch启用安全认证时: ```nginx location /es/ { proxy_pass http://es.huayunworld.com:9200/; proxy_set_header Authorization "Basic ZWxhc3RpYzplbGFzdGlj"; # Base64编码的认证信息 proxy_set_header X-Forwarded-Proto $scheme; rewrite ^/es/(.*)$ /$1 break; # 路径重写(如将/es/foo重定向到/foo) } ``` **关键步骤**: 1. **生成Base64凭证**: ```bash echo -n '用户名:密码' | base64 # 输出结果填入Authorization头 ``` 2. **路径重写**:`rewrite`指令处理URL前缀[^4][^5] --- #### 三、Kubernetes环境配置示例(引用[3]) ```yaml apiVersion: v1 kind: ConfigMap metadata: name: nginx-conf data: nginx.conf: | server { listen 9200; location / { proxy_pass http://elasticsearch:9200; proxy_set_header Authorization "Basic xxxxxxx"; # Base64凭证 } } --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: template: spec: containers: - name: nginx image: nginx:1.18.0 volumeMounts: - name: nginx-conf mountPath: /etc/nginx/nginx.conf --- apiVersion: v1 kind: Service metadata: name: elasticsearch-nginx spec: ports: - port: 9200 targetPort: 9200 ``` --- #### 四、最佳实践与注意事项 1. **安全加固**: - 通过HTTPS访问:添加SSL证书配置 - IP白名单:使用`allow/deny`限制访问来源 ```nginx location / { allow 192.168.1.0/24; deny all; } ``` 2. **性能优化**: - 启用连接池:`keepalive 100;` - 调整缓冲区:`proxy_buffers 16 32k;` 3. **路径处理**: - Kibana代理需特殊配置(如引用[4]的`/kibana/`路径) 4. **集群负载均衡**: ```nginx upstream es_cluster { server 192.168.1.10:9200; server 192.168.1.11:9200; } location / { proxy_pass http://es_cluster; } ``` > **故障排查**: > - 检查Nginx错误日志:`tail -f /var/log/nginx/error.log` > - 测试代理连通性:`curl -H "Authorization: Basic xxx" http://nginx:9200/_cluster/health` > - 验证路径重写:`curl -v http://nginx/es/_cat/indices` 通过上述配置,可实现安全的Elasticsearch访问代理,同时隐藏后端集群细节。实际部署时需根据网络环境和安全需求调整参数[^2][^3][^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值