summaryrefslogtreecommitdiff
blob: 0b24063df0155ce18398069fa90ee2926c5fac5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# This is a very very minimal rsync config that gives ratelimit and ban messages

global
   lua-load 01-deny-rsync.lua

frontend fe_rsync
  mode tcp
  bind *:9873
  tcp-request content set-var(txn.rsync_deny_message) str("") # Start empty
  # Track the backend state
  acl rsync_dead nbsrv(be_rsync)  lt 1
  # Clients will see 'rsync: did not see server greeting'
  tcp-request content reject if rsync_dead
  # Clients will see 'rsync offline'
  tcp-request content set-var(txn.rsync_deny_message) str("rsync offline") if rsync_dead

  # Track abuse
  stick-table type ip size 200k expire 30s store  gpc0,conn_rate(10s),http_req_rate(10s)
  acl source_is_abuser src_get_gpc0 gt 0
  acl conn_rate_abuse  sc1_conn_rate gt 3
  acl mark_as_abuser   sc1_inc_gpc0  ge 0
  tcp-request connection track-sc1 src
  tcp-request content set-var(txn.rsync_deny_message) str("BANHAMMER") if conn_rate_abuse mark_as_abuser source_is_abuser

  # If the deny message is longer than zero, issue deny message
  # Clients will see the message and the rsync client will exit with a SUCCESS state!
  tcp-request content use-service lua.deny-rsync if { var(txn.rsync_deny_message) -m len gt 0 }

  # Otherwise use the backend
  default_backend be_rsync

backend be_rsync
   mode tcp
   # This gives pure HAProxy check
   # Other alternatives would be external-check that execs rsync or very
   # bleeding edge lua-check
   option tcp-check
   tcp-check connect
   # Step 1
   tcp-check comment "Client Initialization"
   tcp-check send "@RSYNCD: 28.0\n"
   # Step 2
   tcp-check comment "Server Initialization"
   tcp-check expect rstring "@RSYNCD: [0-9.]+"
   # Step 3
   tcp-check comment "Client Query (module name rsync-health)"
   tcp-check send "rsync-health\n"
   # Step 4
   tcp-check comment "Data (module name rsync-health)"
   tcp-check expect string "@RSYNCD: OK\n"
   # If the directory for the healthcheck does not exist, rsync will generate
   # "@ERROR: chroot failed"
   # Step 5 
   tcp-check comment "Cleanup"
   tcp-check send "@RSYNCD: EXIT\n"
   # This still leads to messy logs in rsync itself
   # and rsync doesn't have the original source IP (does it really need it?)
   # rsyncd[6562]: connect from localhost (127.0.0.1)
   # rsyncd[6562]: rsync: safe_read failed to read 1 bytes [Receiver]: Connection reset by peer (104)
   # rsyncd[6562]: rsync error: error in rsync protocol data stream (code 12) at io.c(276) [Receiver=3.1.3]

   # This is where we'd put the realservers using discovery
   server localhost localhost:873 check
   # Service discovery instead would look like:
   #server-template gentoo-rsync 50 _gentoo-rsync._tcp.service.consul resolvers consul resolve-prefer ipv4 maxconn 64 check rise 3 fall 2 check

#resolvers consul
#  nameserver consul $consul-client-ip:8600
#  resolve_retries 30
#  timeout retry 2s
#  hold valid 120s
#  accepted_payload_size 8192