|
Lines 788-794
notify_hostkeys(struct ssh *ssh)
Link Here
|
| 788 |
* all connections are dropped for startups > max_startups |
788 |
* all connections are dropped for startups > max_startups |
| 789 |
*/ |
789 |
*/ |
| 790 |
static int |
790 |
static int |
| 791 |
drop_connection(int startups) |
791 |
should_drop_connection(int startups) |
| 792 |
{ |
792 |
{ |
| 793 |
int p, r; |
793 |
int p, r; |
| 794 |
|
794 |
|
|
Lines 805-814
drop_connection(int startups)
Link Here
|
| 805 |
p += options.max_startups_rate; |
805 |
p += options.max_startups_rate; |
| 806 |
r = arc4random_uniform(100); |
806 |
r = arc4random_uniform(100); |
| 807 |
|
807 |
|
| 808 |
debug("drop_connection: p %d, r %d", p, r); |
808 |
debug("%s: p %d, r %d", __func__, p, r); |
| 809 |
return (r < p) ? 1 : 0; |
809 |
return (r < p) ? 1 : 0; |
| 810 |
} |
810 |
} |
| 811 |
|
811 |
|
|
|
812 |
/* |
| 813 |
* Check whether connection should be accepted by MaxStartups. |
| 814 |
* Returns 0 if the connection is accepted. If the connection is refused, |
| 815 |
* returns 1 and attempts to send notification to client. |
| 816 |
* Logs when the MaxStartups condition is entered or exited, and periodically |
| 817 |
* while in that state. |
| 818 |
*/ |
| 819 |
static int |
| 820 |
drop_connection(int sock, int startups) |
| 821 |
{ |
| 822 |
char *laddr, *raddr; |
| 823 |
const char msg[] = "Exceeded MaxStartups\r\n"; |
| 824 |
static time_t last_drop, first_drop; |
| 825 |
static u_int ndropped; |
| 826 |
LogLevel drop_level = SYSLOG_LEVEL_VERBOSE; |
| 827 |
time_t now; |
| 828 |
|
| 829 |
now = monotime(); |
| 830 |
if (!should_drop_connection(startups)) { |
| 831 |
if (last_drop != 0 && |
| 832 |
startups < options.max_startups_begin - 1) { |
| 833 |
/* XXX maybe need better hysteresis here */ |
| 834 |
logit("exited MaxStartups throttling after %s, " |
| 835 |
"%u connections dropped", |
| 836 |
fmt_interval((u_int)(now - first_drop)), ndropped); |
| 837 |
last_drop = 0; |
| 838 |
} |
| 839 |
return 0; |
| 840 |
} |
| 841 |
|
| 842 |
#define SSHD_MAXSTARTUPS_LOG_INTERVAL (5 * 60) |
| 843 |
if (last_drop == 0) { |
| 844 |
error("beginning MaxStartups throttling"); |
| 845 |
drop_level = SYSLOG_LEVEL_INFO; |
| 846 |
first_drop = now; |
| 847 |
ndropped = 0; |
| 848 |
} else if (last_drop + SSHD_MAXSTARTUPS_LOG_INTERVAL < now) { |
| 849 |
/* Periodic logs */ |
| 850 |
error("in MaxStartups throttling for %s, " |
| 851 |
"%u connections dropped", |
| 852 |
fmt_interval((u_int)(now - first_drop)), ndropped + 1); |
| 853 |
drop_level = SYSLOG_LEVEL_INFO; |
| 854 |
} |
| 855 |
last_drop = now; |
| 856 |
ndropped++; |
| 857 |
|
| 858 |
laddr = get_local_ipaddr(sock); |
| 859 |
raddr = get_peer_ipaddr(sock); |
| 860 |
do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d " |
| 861 |
"past MaxStartups", startups, raddr, get_peer_port(sock), |
| 862 |
laddr, get_local_port(sock)); |
| 863 |
free(laddr); |
| 864 |
free(raddr); |
| 865 |
/* best-effort notification to client */ |
| 866 |
(void)write(sock, msg, sizeof(msg) - 1); |
| 867 |
return 1; |
| 868 |
} |
| 869 |
|
| 812 |
static void |
870 |
static void |
| 813 |
usage(void) |
871 |
usage(void) |
| 814 |
{ |
872 |
{ |
|
Lines 1152-1178
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1152 |
usleep(100 * 1000); |
1210 |
usleep(100 * 1000); |
| 1153 |
continue; |
1211 |
continue; |
| 1154 |
} |
1212 |
} |
| 1155 |
if (unset_nonblock(*newsock) == -1) { |
1213 |
if (unset_nonblock(*newsock) == -1 || |
| 1156 |
close(*newsock); |
1214 |
drop_connection(*newsock, startups) || |
| 1157 |
continue; |
1215 |
pipe(startup_p) == -1) { |
| 1158 |
} |
|
|
| 1159 |
if (drop_connection(startups) == 1) { |
| 1160 |
char *laddr = get_local_ipaddr(*newsock); |
| 1161 |
char *raddr = get_peer_ipaddr(*newsock); |
| 1162 |
char msg[] = "Exceeded MaxStartups\r\n"; |
| 1163 |
|
| 1164 |
verbose("drop connection #%d from [%s]:%d " |
| 1165 |
"on [%s]:%d past MaxStartups", startups, |
| 1166 |
raddr, get_peer_port(*newsock), |
| 1167 |
laddr, get_local_port(*newsock)); |
| 1168 |
free(laddr); |
| 1169 |
free(raddr); |
| 1170 |
/* best-effort notification to client */ |
| 1171 |
(void)write(*newsock, msg, strlen(msg)); |
| 1172 |
close(*newsock); |
| 1173 |
continue; |
| 1174 |
} |
| 1175 |
if (pipe(startup_p) == -1) { |
| 1176 |
close(*newsock); |
1216 |
close(*newsock); |
| 1177 |
continue; |
1217 |
continue; |
| 1178 |
} |
1218 |
} |