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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

前言

这篇文章是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>我们正在讨论Elasticsearch的安全配置,特别是关于HTTPSSL身份验证的问题。用户的问题:为什么在Elasticsearch中关闭HTTPSSL身份验证后才能通过网页访问?以及相关的配置说明。根据引用内容,我们可以知道:1.Elasticsearch的安全特性(包括SSL/TLS加密)是通过X-Pack提供的(引用[2])。2.默认情况下,基本许可证(开源版)的安全特性是禁用的(引用[2])。3.我们可以通过配置elasticsearch.yml文件来启用或禁用安全特性。具体到HTTPSSL身份验证:-HTTP层对应的是Elasticsearch的RESTAPI,通常通过9200端口访问。-当启用HTTPSSL(即配置了`xpack.security.http.ssl.enabled`)时,客户端(包括浏览器)必须通过HTTPS访问,并且需要验证服务器的证书。-如果同时启用了HTTP身份验证(即`xpack.security.http.ssl.client_authentication`,默认为`optional`或`required`),则客户端还需要提供证书进行双向认证。用户提到“关闭HTTPSSL身份验证后可通过网页访问”,这里可能有两种情况:1.关闭了整个HTTP层的SSL(即设置`xpack.security.http.ssl.enabled:false`),那么访问将使用HTTP(非加密),因此浏览器可以直接通过HTTP访问。2.或者只是关闭了客户端身份验证(即设置`xpack.security.http.ssl.client_authentication:none`),但SSL加密仍然启用(即仍然使用HTTPS),这样浏览器访问时不需要提供客户端证书,但连接仍然是加密的。因此,关闭HTTPSSL身份验证后可以通过网页访问的原因可能是:-当关闭SSL加密使用HTTP)时,浏览器可以直接访问(但这样不安全)。-当只关闭客户端身份验证(但保持SSL加密)时,浏览器可以通过HTTPS访问,且不需要提供客户端证书(单向SSL,只需服务器证书)。配置说明(在elasticsearch.yml中):1.关闭整个HTTPSSL加密使用HTTP):```yamlxpack.security.http.ssl.enabled:false```这样,ElasticsearchHTTP层将使用明文传输,浏览器可以通过http://<ip>:9200访问。2.关闭HTTPSSL的客户端身份验证(但仍保持HTTPS加密):```yamlxpack.security.http.ssl.enabled:truexpack.security.http.ssl.client_authentication:none```这样,浏览器可以通过https://<ip>:9200访问,但不需要提供客户端证书(只需要信任服务器证书)。注意:关闭SSL加密或客户端身份验证会降低安全性,不推荐在生产环境中使用。另外,引用[2]中提到,启用安全特性需要配置TLS/SSL证书。如果关闭了SSL,那么就不需要配置证书了。但是,为什么关闭后才能通过网页访问?可能的原因是:-在启用SSL且要求客户端身份验证时,浏览器访问需要提供客户端证书。如果用户没有配置客户端证书,或者浏览器没有安装客户端证书,那么访问会被拒绝。-关闭SSL或关闭客户端身份验证后,浏览器可以像访问普通网站一样访问Elasticsearch(如果是关闭SSL则用HTTP,如果是关闭客户端认证则用HTTPS且不需要客户端证书),因此可以访问。因此,用户可能在启用SSL和客户端认证时无法通过浏览器访问,关闭后就可以访问了。安全建议:在生产环境中,建议保持SSL加密,并且根据安全级别决定是否启用客户端认证。如果只是内部使用,可以关闭客户端认证(即单向SSL)以简化访问。但对外暴露的服务,建议使用反向代理(如Nginx)来处理SSL和身份验证,而不是直接关闭。下面我们给出配置示例:示例1:完全禁用HTTPSSL(使用HTTP,不安全)```yaml#在elasticsearch.yml中xpack.security.enabled:true#启用安全特性(如果不需要安全特性,可以设置为false,但这样会完全关闭安全,不推荐)xpack.security.http.ssl.enabled:false```示例2:启用HTTPSSL但禁用客户端认证使用HTTPS,单向认证)```yamlxpack.security.enabled:truexpack.security.http.ssl.enabled:truexpack.security.http.ssl.client_authentication:none#必须配置服务器证书和私钥xpack.security.http.ssl.key:/path/to/http.keyxpack.security.http.ssl.certificate:/path/to/http.crt```注意:如果只配置了SSL而没有配置证书,Elasticsearch使用自签证书,但浏览器会提示证书不受信任。最后,引用[1][2][3]提供了关于Elasticsearch安全配置的更多信息,建议参考。根据用户的问题,我们主要解释了关闭HTTPSSL身份验证后能通过网页访问的原因,并给出了配置说明。</think>### Elasticsearch 关闭 HTTP SSL 身份验证后可通过网页访问的原因及配置说明 #### 原因分析 1. **HTTP SSL 身份验证的作用** 当启用 HTTP SSL(`xpack.security.http.ssl.enabled=true`)时,Elasticsearch 强制要求所有 HTTP 通信必须通过 **HTTPS 加密通道**访问,且客户端需提供有效证书进行身份验证。这会阻止普通网页浏览器的直接访问,因为: - 浏览器默认使用 HTTP(非加密)协议访问 9200 端口。 - 浏览器无法自动提供客户端证书(需手动配置)。 2. **关闭后的访问机制** 关闭 HTTP SSL 身份验证(如设置 `xpack.security.http.ssl.enabled=false`)后: - Elasticsearch **降级为 HTTP 明文通信**。 - 浏览器可直接通过 `http://<ip>:9200` 访问 REST API 或集群状态页面。 - 无需证书验证,绕过 TLS 握手和客户端认证流程。 #### 关键配置说明 在 `elasticsearch.yml` 中修改以下参数: ```yaml # 关闭 HTTP 层 SSL 加密(允许 HTTP 访问) xpack.security.http.ssl.enabled: false # 可选:同时禁用传输层安全(内部节点通信) xpack.security.transport.ssl.enabled: false # 确保安全模块已启用(基础许可证下仍可关闭 SSL) xpack.security.enabled: true ``` #### 安全风险与建议 1. **风险提示** - 🔐 **数据泄露**:HTTP 通信为明文传输,敏感数据(如密码、索引内容)可被截获。 - ⚠️ **未授权访问**:无 SSL 时,无法验证客户端身份,可能引发越权操作。 2. **替代方案(推荐)** 若需兼顾访问便利与安全: - **单向 HTTPS**:启用 SSL 但关闭客户端认证(`client_authentication: none`),浏览器可通过 `https://<ip>:9200` 访问(需忽略证书警告)。 - **反向代理**:通过 Nginx/Apache 配置 HTTPS 终端,代理到 ElasticsearchHTTP 端口[^2]。 > **生产环境警告**:关闭 HTTP SSL 违反 Elasticsearch 安全最佳实践,仅限测试环境使用。生产环境必须启用 TLS 加密和身份验证[^1][^2]。 --- ### 相关问题 1. **如何为 Elasticsearch 配置单向 HTTPS(无需客户端证书)?** 2. **启用 Elasticsearch 传输层加密(TLS)后,节点间通信如何避免证书验证失败?** 3. **Kibana 连接启用 HTTPS 的 Elasticsearch 时出现证书错误,应如何解决?** [^1]: 配置 SSL、TLS 以及 HTTPS 来确保 Elasticsearch、Kibana、Beats 和 Logstash 的安全。 [^2]: 对生产环境的 Elasticsearch 集群开启安全特性是必要的,而 Elastic Stack 已经提供了基于 X-PACK 的安全能力。 [^3]: Elasticsearch使用标准 Java HTTP 的集成 - Elastic Stack 8.x。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值