正向代理系统部署笔记
概述
正向代理系统在目前的业务场景中可谓愈来愈少了。今时难得有个场景需要它,于是就有了这篇文章。
服务器为安全需求,默认禁止让内网中的服务器主动去访问公网,然而有些业务系统又必须依赖外网资源,如:
- 商业软件
License
定期访问指定服务器验证 - 业务系统调用公共API接口
- 等等。。。
目前,以上的种种需求都是通过防火墙ACL策略来实现,防火墙配置的策略繁琐、低效率、易出错、依赖性强,站在技术立场不建议在防火墙ACL去管控上述的各类需求。
正向代理可以有效的替代防火墙当前的管制手段,即所有的内部服务器出公网的数据请求都通过正向代理系统,我们只需审计正向代理出公网的日志即可。通俗一点说就是我们需要一套 正向系统 + 日志系统。
Squid 是一老牌的代理软件,功能强大,性能不俗。
ELK 是流行的日志框架系统。
架构
通过filebeat将代理服务器的日志发送到logstash,以便管理员通过kibana进行分析/可视化。
环境
squid
:代理服务器squidGuard
:squid的过滤器,可以过滤URL或域名Filebeat
:将日志发送至logstashLogistash
:将filebeat收到的日志标为过滤Elasticsearch
:数据的索引制作和保存kibana
:数据的可视化和分析
版本这里使用最版本的
7.7
,ELK 仓库使用https://mirrors.tuna.tsinghua.edu.cn/
Filebeat安装
使用RPM包安装
# rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/7.7.0/filebeat-7.7.0-x86_64.rpm
Filebeat配置
编辑 /etc/filebeat/filebeat.yml
配置文件,编辑内容如下:
filebeat.inputs:
- type: log
paths:
- /var/log/squid/access.log
output.logstash:
hosts: ["Logstash_IP:5044"]
服务启动
# systemctl enable filebeat
# systemctl start filebeat
squid配置
日志输出格式
默认的日志格式不能满足我们的需求,需要进其进一步定义输出。
squid.conf
logformat access-lt %{%Y-%m-%d}tg %{%H:%M:%S}tl.%03tu %>a:%>p %ui %un %<A "%rm %ru HTTP/%rv" "%{Referer}>h" "%{User-Agent}>h" "%{Cookie}>h" %>Hs %>st %tr %<st %mt %Ss:%Sh
access_log /var/log/squid/access.log access-lt
squid.conf配置范例
cache_mgr qiush@vqiu.cn
http_port 80
cache_dir ufs /var/spool/squid 1000 16 256
coredump_dir /var/spool/squid
# Visible Hostname
visible_hostname proxy.vqiu.cn
# Cache size
cache_mem 384 MB
# Proxy DNS Server
dns_nameservers 223.5.5.5 223.6.6.6
# Error Display
error_directory /usr/share/squid/errors/zh-cn
# Auth
#auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/.htpasswd
#auth_param basic children 5
#auth_param basic realm Squid Basic Authentication
#auth_param basic credentialsttl 5 hours
#acl password proxy_auth REQUIRED
#http_access allow password
#
http_access allow all
# not display IP address
forwarded_for off
# header
request_header_access Referer deny all
request_header_access X-Forwarded-For deny all
request_header_access Via deny all
request_header_access Cache-Control deny all
# add follows to the end
url_rewrite_program /usr/bin/squidGuard -c /etc/squid/squidGuard.conf
logformat access-lt %{%Y-%m-%d}tg %{%H:%M:%S}tl.%03tu %>a:%>p %ui %un %<A "%rm %ru HTTP/%rv" "%{Referer}>h" "%{User-Agent}>h" "%{Cookie}>h" %>Hs %>st %tr %<st %mt %Ss:%Sh
access_log /var/log/squid/access.log access-lt
以上包含squidGuard的配置
关于squidGuard移步至:https://www.server-world.info/en/note?os=CentOS_7&p=squid&f=6
logstash安装/配置
安装Java环境
logstash 依赖java,所以在安装logstash之前必须把java给管上,这里我们可以使用OenJDK
# yum -y install java-11-openjdk
安装logstash
# rpm -ivh https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/7.7.0/logstash-7.7.0.rpm
为squid输出日志创建过滤器
squid日志输出样例如下:
2020-05-16 01:21:58.606 127.0.0.1:53438 - - www.n-novice.com "GET http://www.n-novice.com/entry/2018/07/05/000000 HTTP/1.1" "-" "curl/7.29.0" "-" 301 156 392 924 text/html TCP_MISS:HIER_DIRECT
2020-05-16 01:45:56.445 10.10.100.20:57917 - - api2.firefoxchina.cn "CONNECT api2.firefoxchina.cn:443 HTTP/1.1" "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0" "-" 200 1237 60090 3928 - TCP_TUNNEL:HIER_DIRECT
创建/设置过滤器
创建/etc/logstash/conf.d/01-squid.conf
,并追加内容如下:
input {
beats {
port => "5044"
type => "beats"
}
}
filter {
if [type] == "beats" {
grok {
match => [ "message", "%{TIMESTAMP_ISO8601:s_timestamp} %{IPORHOST:src_ip}:%{POSINT:src_port} %{USER:ident} %{USER:auth} %{USERNAME:req_domain} \"%{DATA:method} %{NOTSPACE:request} (?:HTTP/%{NUMBER:httpversion})\" \"%{NOTSPACE:referer}\" \"%{DATA:send_headers}\" \"%{DATA:cookes}\" %{INT:request_code} %{INT:request_size} %{INT:response_time} %{INT:response_size} %{DATA:mime} %{GREEDYDATA:squid_status}" ]
}
date{
match => ["s_timestamp" , "yyyy-MM-dd_HH-mm-ss.SSS"]
timezone => "Asia/Shanghai"
}
useragent {
source => "send_headers"
target => "useragent"
}
}
}
output {
if [type] == "beats" {
elasticsearch {
hosts => ["ES_IP:9200"]
index => "squid-%{+YYYY.MM}"
}
}
}
赋予权限
# chown logstash. /etc/logstash/conf.d/01-squid.conf
重启logstash服务
//重启服务
# systemctl restart logstash
//查看启用日志
# tail -f /var/log/logstash/logstash-plain.log
日志预览
扩展
关于多台服务器
目前的架构是基于单机的,如果内网存在一定的规模,需要部署多台,常规的做法是接入LB(负载均衡),但是这里会存在真实源IP的问题--获取的源IP都是LB地址,所以不是我们想要的。这时候可以使用以下技术去横向扩展:
- 使用动态路由(OSPF或BGP)建立ECMP(线下我比较偏爱的一种架构)
- 使用LVS FULLNAT(有杀鸡用牛刀之嫌)
- 使用透明网关代理
- 使用HAproxy的proxy_protocol协议(Haproxy/nginx)
负载均衡使用proxy_protocol
获取真实源IP
后端 squid 配置
squid.conf
acl frontend src 10.10.100.9
http_port 3128 require-proxy-header
#http_port 3128 accel require-proxy-header
proxy_protocol_access allow frontend
- frontend:负载均衡的IP地址,有多台就写多条
更多配置参考: http://squid.mirror.colo-serv.net/archive/3.5/squid-3.5.18-RELEASENOTES.html#ss2.7
Haproxy
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
#stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend squid
bind 80
default_backend squid_pool
backend squid_pool
balance roundrobin
mode tcp
server squid1 xx.xx.xx.xx.:3128 check send-proxy
server squid2 xx.xx.xx.xx.:3128 check send-proxy
1.5版本以上
nginx
stream {
log_format basic '{"@access_time":"$time_iso8601",'
'"clientip":"$remote_addr",'
'"pid":$pid,'
'"pro":"$protocol",'
'"stus":$status,'
'"sent":$bytes_sent,'
'"recv":$bytes_received,'
'"sess_time":$session_time}';
server {
listen 80;
proxy_pass 127.0.0.1:3128;
proxy_protocol on;
access_log /var/log/nginx/stream.log basic;
error_log /var/log/nginx/error.log;
}
}
对外发布LB
的业务IP为业务入口即可(如: proxy.vqiu.cn
),Squid
后端可以通过proxy_protocol
正常获取真实客户端的IP。
另: 如果觉得squid过于重量,可以使用 nginx + ngx_http_proxy_connect
,具体部署细节不表,有兴趣者自行研究。