GOLANG, HTTP having "use of closed network connection" error - http

I am getting a lot of error like below mentioned,
read tcp xx.xx.xx.xx:80: use of closed network connection
read tcp xx.xx.xx.xx:80: connection reset by peer
//function for HTTP connection
func GetResponseBytesByURL_raw(restUrl, connectionTimeOutStr, readTimeOutStr string) ([]byte, error) {
connectionTimeOut, _ /*err*/ := time.ParseDuration(connectionTimeOutStr)
readTimeOut, _ /*err*/ := time.ParseDuration(readTimeOutStr)
timeout := connectionTimeOut + readTimeOut // time.Duration((strconv.Atoi(connectionTimeOutStr) + strconv.Atoi(readTimeOutStr)))
//timeout = 200 * time.Millisecond
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(restUrl)
if nil != err {
logger.SetLog("Error GetResponseBytesByURL_raw |err: ", logs.LevelError, err)
return make([]byte, 0), err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return body, err
}
Update (July 14):
Server : NumCPU=8, RAM=24GB, GO=go1.4.2.linux-amd64
I am getting such error during some high traffic.
20000-30000 request per minutes, and I have a time frame of 500ms to fetch response from third party api.
netstat status from my server (using : netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n) to get frequency
1 established)
1 Foreign
9 LISTEN
33 FIN_WAIT1
338 ESTABLISHED
5530 SYN_SENT
32202 TIME_WAIT
sysctl -p
**sysctl -p**
fs.file-max = 2097152
vm.swappiness = 10
vm.dirty_ratio = 60
vm.dirty_background_ratio = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.ip_local_port_range = 2000 65535
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_fin_timeout = 5
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.core.rmem_default = 31457280
net.core.rmem_max = 12582912
net.core.wmem_default = 31457280
net.core.wmem_max = 12582912
net.core.somaxconn = 65536
net.core.netdev_max_backlog = 65536
net.core.optmem_max = 25165824
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144
net.ipv4.tcp_rmem = 8192 87380 16777216
net.ipv4.udp_rmem_min = 16384
net.ipv4.tcp_wmem = 8192 65536 16777216
net.ipv4.udp_wmem_min = 16384
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv6.bindv6only = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
error: "net.ipv4.icmp_ignore_bogus_error_messages" is an unknown key
kernel.exec-shield = 1
kernel.randomize_va_space = 1
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0

When making connections at a high rate over the internet, it's very likely you're going to encounter some connection problems. You can't mitigate them completely, so you may want to add retry logic around the request. The actual error type at this point probably doesn't matter, but matching the error string for use of closed network connection or connection reset by peer is about the best you can do if you want to be specific. Make sure to limit the retries with a backoff, as some systems will drop or reset connections as a way to limit request rates, and you may get more errors the faster you reconnect.
Depending on the number of remote hosts you're communicating with, you will want to increase Transport.MaxIdleConnsPerHost (the default is only 2). The fewer hosts you talk to, the higher you can set this. This will decrease the number of new connections made, and speed up the requests overall.
If you can, try the go1.5 beta. There have been a couple changes around keep-alive connections that may help reduce the number of errors you see.

I recommend implementing an exponential back off or some other rate limiting mechanism on your side of the wire. There's not really anything you can do about those error, and using exponential back off won't necessarily make you get the data any faster either. But it can ensure that you get all the data and the API you're pulling from will surely appreciate the reduced traffic. Here's a link to one I found on GitHub; https://github.com/cenkalti/backoff
There was another popular option as well though I haven't used either. Implementing one yourself isn't terribly difficult either and I could provide some sample of that on request. One thing I do recommend based off my experience is make sure you're using a retry function that has an abort channel. If you get to really long back off times then you'll want some way for the caller to kill it.

Related

how to extract ip address from QueueDiscItem in ns3?

I'm new to NS3 and i was trying to extract ip address of a packet from QueueDiscItem,
when i have:
Ptr< QueueDiscItem > item initiated and call:
item->Print(std::cout);
the output i get is
"tos 0x0 DSCP Default ECN Not-ECT ttl 63 id 265 protocol 6 offset (bytes) 0 flags [none] length: 76 10.1.4.2 > 10.1.2.1 0x7fffc67ec880 Dst addr 02-06-ff:ff:ff:ff:ff:ff proto 2048 txq"
but when i call:
Ipv4Header header;
item->GetPacket()->PeekHeader(header);
header.Print(std::cout);
the output i get is
"tos 0x0 DSCP Default ECN Not-ECT ttl 0 id 0 protocol 0 offset (bytes) 0 flags [none] length: 20 102.102.102.102 > 102.102.102.102"
How to get the Header data
According to the list of TraceSources, the TraceSources associated with QueueDiscItems are for Queues. I'm guessing you were trying to attach to one of those TraceSources.
A QueueDiscItem encapsulates several things: a Ptr<Packet>, a MAC address, and several more things. Since you are using IPv4, the QueueDiscItem is actually an Ipv4QueueDiscItem (the latter is a subclass of the former). So, let's start by casting the QueueDiscItem to an Ipv4QueueDiscItem by
Ptr<const Ipv4QueueDiscItem> ipItem = DynamicCast<const Ipv4QueueDiscItem>(item);
Next, you need to know that at this point in the simulation, the Ipv4Header has not been added to the Ptr<Packet> yet. This is probably a design choice (that I don't understand). So, how can we get this information? Well, the Ipv4QueueDiscItem encapsulates the Ipv4Header, and at some point before passing the Ptr<Packet> to L2, the header is added to the packet. This Header can be retrieved by
const Ipv4Header ipHeader = ipItem->GetHeader();
So, now we have the Ipv4Header of the packet you're interested in. Now, we can safely get the address from the Ipv4QueueDiscItem by
ipHeader.GetSource();
ipHeader.GetDestination();
In summary, your TraceSource function should look something like this:
void
EnqueueTrace (Ptr<const QueueDiscItem> item) {
Ptr<const Ipv4QueueDiscItem> ipItem = DynamicCast<const Ipv4QueueDiscItem>(item);
const Ipv4Header ipHeader = ipItem->GetHeader();
NS_LOG_UNCOND("Packet received at " << Simulator::Now() << " going from " << ipHeader.GetSource() << " to " << ipHeader.GetDestination());
}
Why does item->Print(std::cout); work?
All of the above makes sense, but why does
item->Print(std::cout);
print the correct addresses? First, it is important to realize that here Print() is a function of the QueueDiscItem, not the Packet. If we go to the source of this function, we find that Print() just prints the Header if it has already been added.

Delayed outgoing mail in active queue

I am stuck for some time trying to set up an email server. I've been mostly successful in my setup, but I am currently stuck at the following impasse: every time I send an email (regardless of queue size), my message will get stuck in the active queue for ~ 5 minutes, after which it will always be sent and reach it's final destination.
postqueue -p
(shows only one mail in the queue)
postqueue -f
... has no effect
I am running postfix 3.1.0, and dovecot 2.2.22 on Ubuntu 16.04. Also, I used iRedMail scripts for the installation. I can see from /var/log/mail.log that the mail is being stored in a queue by postfix, and I'm assuming there's another setting to set the time at which it will be processed. Any help would be most appreciated.
/var/log/mail.log
Jan 9 14:35:28 mail postfix[26070]: name_mask: all
Jan 9 14:35:28 mail postfix[26070]: inet_addr_local: configured 2 IPv4 addresses
Jan 9 14:35:28 mail postfix[26070]: inet_addr_local: configured 3 IPv6 addresses
Jan 9 14:35:28 mail postfix/postfix-script[26075]: error: unknown command: ''
Jan 9 14:35:28 mail postfix/postfix-script[26076]: fatal: usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration)
Jan 9 14:35:49 mail postfix[26085]: fatal: usage: postfix [-c config_dir] [-Dv] command
Jan 9 14:35:58 mail postfix[26090]: fatal: usage: postfix [-c config_dir] [-Dv] command
Jan 9 14:40:17 mail postfix/submission/smtpd[26282]: connect from mail.example.com[127.0.0.1]
Jan 9 14:40:17 mail postfix/submission/smtpd[26282]: Anonymous TLS connection established from mail.example.com[127.0.0.1]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
Jan 9 14:40:17 mail postfix/submission/smtpd[26282]: 87ABB42362: client=mail.example.com[127.0.0.1], sasl_method=PLAIN, sasl_username=jamal#example.com
Jan 9 14:40:17 mail postfix/cleanup[26288]: 87ABB42362: message-id=<0130a1e7b419fdf0f31ce406618aef97#example.com>
Jan 9 14:40:17 mail postfix/qmgr[28474]: 87ABB42362: from=, size=1845, nrcpt=1 (queue active)
Jan 9 14:40:17 mail postfix/submission/smtpd[26282]: disconnect from mail.example.com[127.0.0.1] ehlo=2 starttls=1 auth=1 mail=1 rcpt=1 data=1 quit=1 commands=8
Jan 9 14:45:05 mail amavis[10642]: (10642-08) (!)ClamAV-clamd av-scanner FAILED: run_av error: ask_daemon_internal: Exceeded allowed time at (eval 104) line 611.\n
Jan 9 14:45:05 mail amavis[10642]: (10642-08) (!)WARN: all primary virus scanners failed, considering backups
Jan 9 14:45:05 mail amavis[10642]: (10642-08) (!!)AV: ALL VIRUS SCANNERS FAILED
Jan 9 14:45:07 mail postfix/postqueue[26446]: fatal: usage: postqueue -f | postqueue -i queueid | postqueue -j | postqueue -p | postqueue -s site
Jan 9 14:45:08 mail postfix/10025/smtpd[26452]: connect from mail.example.com[127.0.0.1]
Jan 9 14:45:08 mail postfix/10025/smtpd[26452]: 60ADA423BA: client=mail.example.com[127.0.0.1]
Jan 9 14:45:08 mail postfix/cleanup[26454]: 60ADA423BA: message-id=<0130a1e7b419fdf0f31ce406618aef97#example.com>
Jan 9 14:45:08 mail postfix/10025/smtpd[26452]: disconnect from mail.example.com[127.0.0.1] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
Jan 9 14:45:08 mail postfix/qmgr[28474]: 60ADA423BA: from=, size=2920, nrcpt=1 (queue active)
Jan 9 14:45:08 mail amavis[10642]: (10642-08) Passed UNCHECKED {RelayedInternal}, ORIGINATING/MYNETS LOCAL [127.0.0.1]:33748 -> , Queue-ID: 87ABB42362, Message-ID: <0130a1e7b419fdf0f31ce406618aef97#example.com>, mail_id: FFIMhQZ3j_4G, Hits: 0.204, size: 1845, queued_as: 60ADA423BA, dkim_new=dkim:example.com, 290782 ms, Tests: [ALL_TRUSTED=-1,HTML_MESSAGE=0.001,TVD_RCVD_SINGLE=1.213,T_RP_MATCHES_RCVD=-0.01]
Jan 9 14:45:08 mail postfix/amavis/smtp[26293]: 87ABB42362: to=, relay=127.0.0.1[127.0.0.1]:10026, delay=291, delays=0.16/0.03/0.04/291, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 60ADA423BA)
Jan 9 14:45:08 mail postfix/qmgr[28474]: 87ABB42362: removed
Jan 9 14:45:09 mail postfix/smtp[26455]: Untrusted TLS connection established to cornellprod-mail-onmicrosoft-com.mail.eo.outlook.com[216.32.181.106]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)
Jan 9 14:45:09 mail postfix/smtp[26455]: 60ADA423BA: to=, relay=cornellprod-mail-onmicrosoft-com.mail.eo.outlook.com[216.32.181.106]:25, delay=1.6, delays=0.02/0.03/0.64/0.89, dsn=2.6.0, status=sent (250 2.6.0 <0130a1e7b419fdf0f31ce406618aef97#example.com> [InternalId=132499741090511, Hostname=BN3PR0401MB1284.namprd04.prod.outlook.com] 10597 bytes in 0.347, 29.819 KB/sec Queued mail for delivery)
Jan 9 14:45:09 mail postfix/qmgr[28474]: 60ADA423BA: removed
Jan 9 14:45:20 mail postfix/postqueue[26468]: fatal: Flush service is not configured for destination "active"
/etc/postfix/main.cf
# --------------------
# INSTALL-TIME CONFIGURATION INFORMATION
#
# location of the Postfix queue. Default is /var/spool/postfix. queue_directory = /var/spool/postfix
# location of all postXXX commands. Default is /usr/sbin. command_directory = /usr/sbin
# location of all Postfix daemon programs (i.e. programs listed in the
# master.cf file). This directory must be owned by root.
# Default is /usr/libexec/postfix daemon_directory = /usr/lib/postfix/sbin
# location of Postfix-writable data files (caches, random numbers).
# This directory must be owned by the mail_owner account (see below).
# Default is /var/lib/postfix. data_directory = /var/lib/postfix
# owner of the Postfix queue and of most Postfix daemon processes.
# Specify the name of a user account THAT DOES NOT SHARE ITS USER OR GROUP ID
# WITH OTHER ACCOUNTS AND THAT OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM.
# In particular, don't specify nobody or daemon. PLEASE USE A DEDICATED USER.
# Default is postfix. mail_owner = postfix
# The following parameters are used when installing a new Postfix version.
#
# sendmail_path: The full pathname of the Postfix sendmail command.
# This is the Sendmail-compatible mail posting interface.
# sendmail_path = /usr/sbin/sendmail
# newaliases_path: The full pathname of the Postfix newaliases command.
# This is the Sendmail-compatible command to build alias databases.
# newaliases_path = /usr/bin/newaliases
# full pathname of the Postfix mailq command. This is the Sendmail-compatible
# mail queue listing command. mailq_path = /usr/bin/mailq
# group for mail submission and queue management commands.
# This must be a group name with a numerical group ID that is not shared with
# other accounts, not even with the Postfix account. setgid_group = postdrop
# debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
ddd $daemon_directory/$process_name $process_id & sleep 5
debug_peer_level = 2
# --------------------
# CUSTOM SETTINGS
#
# SMTP server response code when recipient or domain not found. unknown_local_recipient_reject_code = 550
# Do not notify local user. biff = no
# Disable the rewriting of "site!user" into "user#site". swap_bangpath = no
# Disable the rewriting of the form "user%domain" to "user#domain". allow_percent_hack = no
# Allow recipient address start with '-'. allow_min_user = no
# Disable the SMTP VRFY command. This stops some techniques used to
# harvest email addresses. disable_vrfy_command = yes
# Enable both IPv4 and/or IPv6: ipv4, ipv6, all. inet_protocols = all
# Enable all network interfaces. inet_interfaces = all
#
# TLS settings.
#
# SSL key, certificate, CA
# smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/cert.pem
smtpd_tls_CAfile = /etc/letsencrypt/live/mail.example.com/chain.pem
#
# Disable SSLv2, SSLv3
# smtpd_tls_protocols = !SSLv2 !SSLv3 smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3 smtp_tls_protocols = !SSLv2 !SSLv3
smtp_tls_mandatory_protocols = !SSLv2 !SSLv3 lmtp_tls_protocols =
!SSLv2 !SSLv3 lmtp_tls_mandatory_protocols = !SSLv2 !SSLv3
#
# Fix 'The Logjam Attack'.
# smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDC3-SHA, KRB5-DE5,
CBC3-SHA smtpd_tls_dh512_param_file = /etc/ssl/dh512_param.pem
smtpd_tls_dh1024_param_file = /etc/ssl/dh2048_param.pem
tls_random_source = dev:/dev/urandom
smtpd_tls_loglevel = 1
# Opportunistic TLS: announce STARTTLS support to remote SMTP clients, but do
# not require that clients use TLS encryption. smtpd_tls_security_level = may
# Produce Received: message headers that include information about the
# protocol and cipher used, as well as the remote SMTP client CommonName and
# client certificate issuer CommonName.
# This is disabled by default, as the information may be modified in transit
# through other mail servers. Only information that was recorded by the final
# destination can be trusted.
#smtpd_tls_received_header = yes
# Opportunistic TLS, used when Postfix sends email to remote SMTP server.
# Use TLS if this is supported by the remote SMTP server, otherwise use
# plaintext.
# References:
# - http://www.postfix.org/TLS_README.html#client_tls_may
# - http://www.postfix.org/postconf.5.html#smtp_tls_security_level smtp_tls_security_level = may
# Use the same CA file as smtpd. smtp_tls_CAfile = $smtpd_tls_CAfile smtp_tls_note_starttls_offer = yes
# Enable long, non-repeating, queue IDs (queue file names).
# The benefit of non-repeating names is simpler logfile analysis and easier
# queue migration (there is no need to run "postsuper" to change queue file
# names that don't match their message file inode number).
#enable_long_queue_ids = yes
# Reject unlisted sender and recipient smtpd_reject_unlisted_recipient = yes smtpd_reject_unlisted_sender = yes
# Header and body checks with PCRE table header_checks = pcre:/etc/postfix/header_checks body_checks =
pcre:/etc/postfix/body_checks.pcre
# A mechanism to transform commands from remote SMTP clients.
# This is a last-resort tool to work around client commands that break
# interoperability with the Postfix SMTP server. Other uses involve fault
# injection to test Postfix's handling of invalid commands.
# Requires Postfix-2.7+.
#smtpd_command_filter = pcre:/etc/postfix/command_filter.pcre
# HELO restriction smtpd_helo_required = yes smtpd_helo_restrictions =
permit_mynetworks
permit_sasl_authenticated
check_helo_access pcre:/etc/postfix/helo_access.pcre
reject_non_fqdn_helo_hostname
reject_unknown_helo_hostname
# Sender restrictions smtpd_sender_restrictions =
reject_unknown_sender_domain
reject_non_fqdn_sender
reject_unlisted_sender
permit_mynetworks
permit_sasl_authenticated
check_sender_access pcre:/etc/postfix/sender_access.pcre
# Recipient restrictions smtpd_recipient_restrictions =
reject_unknown_recipient_domain
reject_non_fqdn_recipient
reject_unlisted_recipient
check_policy_service inet:127.0.0.1:7777
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination
# END-OF-MESSAGE restrictions smtpd_end_of_data_restrictions =
check_policy_service inet:127.0.0.1:7777
# Data restrictions smtpd_data_restrictions = reject_unauth_pipelining
proxy_read_maps = $canonical_maps $lmtp_generic_maps
$local_recipient_maps $mydestination $mynetworks $recipient_bcc_maps
$recipient_canonical_maps $relay_domains $relay_recipient_maps
$relocated_maps $sender_bcc_maps $sender_canonical_maps
$smtp_generic_maps $smtpd_sender_login_maps $transport_maps
$virtual_alias_domains $virtual_alias_maps $virtual_mailbox_domains
$virtual_mailbox_maps $smtpd_sender_restrictions
$sender_dependent_relayhost_maps
# Avoid duplicate recipient messages. Default is 'yes'. enable_original_recipient = no
# Virtual support. virtual_minimum_uid = 2000 virtual_uid_maps = static:2000 virtual_gid_maps = static:2000 virtual_mailbox_base =
/var/vmail
# Do not set virtual_alias_domains. virtual_alias_domains =
#
# Enable SASL authentication on port 25 and force TLS-encrypted SASL authentication.
# WARNING: NOT RECOMMENDED to enable smtp auth on port 25, all end users should
# be forced to submit email through port 587 instead.
#
#smtpd_sasl_auth_enable = yes
#smtpd_sasl_security_options = noanonymous
#smtpd_tls_auth_only = yes
# hostname myhostname = mail.example.com myorigin = mail.example.com mydomain = mail.example.com
# trusted SMTP clients which are allowed to relay mail through Postfix.
#
# Note: additional IP addresses/networks listed in mynetworks should be listed
# in iRedAPD setting 'MYNETWORKS' (in /opt/iredapd/settings.py) too.
# for example:
#
# MYNETWORKS = ['xx.xx.xx.xx', 'xx.xx.xx.0/24', ...]
# mynetworks = 127.0.0.1 [::1]
# Accepted local emails mydestination = $myhostname, localhost, localhost.localdomain
alias_maps = hash:/etc/postfix/aliases alias_database =
hash:/etc/postfix/aliases
# Default message_size_limit. message_size_limit = 15728640
# The set of characters that can separate a user name from its extension
# (example: user+foo), or a .forward file name from its extension (example:
# .forward+foo).
# Postfix 2.11 and later supports multiple characters. recipient_delimiter = +
# The time after which the sender receives a copy of the message headers of
# mail that is still queued. Default setting is disabled (0h) by Postfix.
#delay_warning_time = 1h compatibility_level = 2
#
# Lookup virtual mail accounts
# transport_maps =
proxy:mysql:/etc/postfix/mysql/transport_maps_user.cf
proxy:mysql:/etc/postfix/mysql/transport_maps_domain.cf
sender_dependent_relayhost_maps =
proxy:mysql:/etc/postfix/mysql/sender_dependent_relayhost_maps.cf
# Lookup table with the SASL login names that own the sender (MAIL FROM) addresses. smtpd_sender_login_maps =
proxy:mysql:/etc/postfix/mysql/sender_login_maps.cf
virtual_mailbox_domains =
proxy:mysql:/etc/postfix/mysql/virtual_mailbox_domains.cf
relay_domains =
$mydestination
proxy:mysql:/etc/postfix/mysql/relay_domains.cf
virtual_mailbox_maps =
proxy:mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf
virtual_alias_maps =
proxy:mysql:/etc/postfix/mysql/virtual_alias_maps.cf
proxy:mysql:/etc/postfix/mysql/domain_alias_maps.cf
proxy:mysql:/etc/postfix/mysql/catchall_maps.cf
proxy:mysql:/etc/postfix/mysql/domain_alias_catchall_maps.cf
sender_bcc_maps =
proxy:mysql:/etc/postfix/mysql/sender_bcc_maps_user.cf
proxy:mysql:/etc/postfix/mysql/sender_bcc_maps_domain.cf
recipient_bcc_maps =
proxy:mysql:/etc/postfix/mysql/recipient_bcc_maps_user.cf
proxy:mysql:/etc/postfix/mysql/recipient_bcc_maps_domain.cf
#
# Postscreen
# postscreen_greet_action = enforce postscreen_blacklist_action = enforce postscreen_dnsbl_action = enforce postscreen_dnsbl_threshold =
2 postscreen_dnsbl_sites =
zen.spamhaus.org=127.0.0.[2..11]*3
b.barracudacentral.org=127.0.0.[2..11]*2
postscreen_dnsbl_reply_map =
texthash:/etc/postfix/postscreen_dnsbl_reply postscreen_access_list =
permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr
# Require Postfix-2.11+ postscreen_dnsbl_whitelist_threshold = -2
#
# Dovecot SASL support.
# smtpd_sasl_type = dovecot smtpd_sasl_path = private/dovecot-auth virtual_transport = dovecot dovecot_destination_recipient_limit = 1
#
# Amavisd + SpamAssassin + ClamAV
# content_filter = smtp-amavis:[127.0.0.1]:10024
# Concurrency per recipient limit. smtp-amavis_destination_recipient_limit = 1
/etc/dovecot/dovecot.conf
# More details about Dovecot settings: # -
http://wiki2.dovecot.org/ # - http://wiki2.dovecot.org/Variables
# Listen addresses. # - '*' means all available IPv4 addresses. #
- '[::]' means all available IPv6 addresses. # Listen on all available addresses by default listen = * [::]
#base_dir = /var/run/dovecot mail_plugins = quota mailbox_alias acl
mail_log notify
# Enabled mail protocols. protocols = pop3 imap sieve lmtp
# User/group who owns the message files: mail_uid = 2000 mail_gid =
2000
# Assign uid to virtual users. first_valid_uid = 2000 last_valid_uid
= 2000
# Logging. Reference: http://wiki2.dovecot.org/Logging # # Use
syslog syslog_facility = local5 # Log file path if we use internal
log system #log_path = /var/log/dovecot/dovecot.log
# Debug #mail_debug = yes #auth_verbose = yes #auth_debug = yes
#auth_debug_passwords = yes # Possible values: no, plain, sha1.
#auth_verbose_passwords = no
# SSL: Global settings. # Refer to wiki site for per protocol, ip,
server name SSL settings: #
http://wiki2.dovecot.org/SSL/DovecotConfiguration ssl_protocols =
!SSLv2 !SSLv3 ssl = required verbose_ssl = no #ssl_ca =
# Fix 'The Logjam Attack' ssl_cipher_list =
ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5
# Dovecot 2.2.6 or greater: # Specify the wanted DH parameters
length ssl_dh_parameters_length = 2048 ssl_prefer_server_ciphers = yes
# With disable_plaintext_auth=yes AND ssl=required, STARTTLS is
mandatory. # Set disable_plaintext_auth=no AND ssl=yes to allow plain
password transmitted # insecurely. disable_plaintext_auth = yes
# Allow plain text password per IP address/net #remote
192.168.0.0/24 { # disable_plaintext_auth = no #}
# Mail location and mailbox format. mail_location =
maildir:%Lh/Maildir/:INDEX=%Lh/Maildir/
# Authentication related settings. # Append this domain name if
client gives empty realm. #auth_default_realm = example.com
# Authentication mechanisms. auth_mechanisms = PLAIN LOGIN
# Limits the number of users that can be logging in at the same time.
# Default is 100. This can be overridden by process_limit = in #
service [protocol] block. # e.g. # protocol imap-login { #
... # process_limit = 500 # }
#default_process_limit = 100
service auth {
unix_listener /var/spool/postfix/private/dovecot-auth {
user = postfix
group = postfix
mode = 0666
}
unix_listener auth-master {
user = vmail
group = vmail
mode = 0666
}
unix_listener auth-userdb {
user = vmail
group = vmail
mode = 0660
} }
# LMTP server (Local Mail Transfer Protocol). # Reference:
http://wiki2.dovecot.org/LMTP service lmtp {
user = vmail
\# For higher volume sites, it may be desirable to increase the number of
\# active listener processes. A range of 5 to 20 is probably good for most
\# sites.
process_min_avail = 5
\# Logging.
\# Require 'log_path =' in 'protocol lmtp {}' block.
executable = lmtp -L
\# Listening on socket file and TCP
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
mode = 0600
}
inet_listener lmtp {
\# Listen on localhost (ipv4)
address = 127.0.0.1
port = 24
} }
# Virtual mail accounts. userdb {
args = /etc/dovecot/dovecot-mysql.conf
driver = sql } passdb {
args = /etc/dovecot/dovecot-mysql.conf
driver = sql }
auth_master_user_separator = * passdb {
driver = passwd-file
args = /etc/dovecot/dovecot-master-users
master = yes }
plugin {
# Quota configuration.
# Reference: http://wiki2.dovecot.org/Quota/Configuration
quota = dict:user::proxy::quotadict
quota_rule = *:storage=1G
#quota_rule2 = *:messages=0
#quota_rule3 = Trash:storage=1G
#quota_rule4 = Junk:ignore
\# Quota warning.
\#
\# If user suddenly receives a huge mail and the quota jumps from
\# 85% to 95%, only the 95% script is executed.
\#
\# Only the command for the first exceeded limit is executed, so configure
\# the highest limit first.
quota_warning = storage=100%% quota-warning 100 %u
quota_warning2 = storage=95%% quota-warning 95 %u
quota_warning3 = storage=90%% quota-warning 90 %u
quota_warning4 = storage=85%% quota-warning 85 %u
\# allow user to become max 10% (or 50 MB) over quota
quota_grace = 10%%
\#quota_grace = 50 M
\# Custom Quota Exceeded Message.
\# You can specify the message directly or read the message from a file.
\#quota_exceeded_message = Quota exceeded, please try again later.
\#quota_exceeded_message = </path/to/quota_exceeded_message.txt
\# Plugin: expire.
\#expire = Trash 7 Trash/* 7 Junk 30
\#expire_dict = proxy::expire
\# ACL and share folder
acl = vfile
acl_shared_dict = proxy::acl
\# By default Dovecot doesn't allow using the IMAP "anyone" or
\# "authenticated" identifier, because it would be an easy way to spam
\# other users in the system. If you wish to allow it,
\#acl_anyone = allow
\# Pigeonhole managesieve service.
\# Reference: http://wiki2.dovecot.org/Pigeonhole/Sieve/Configuration
\# Per-user sieve settings.
sieve_dir = %Lh/sieve
sieve = %Lh/sieve/dovecot.sieve
\# Global sieve settings.
sieve_global_dir = /var/vmail/sieve
\# Note: if user has personal sieve script, global sieve rules defined in
\# sieve_default will be ignored. Please use sieve_before or
\# sieve_after instead.
\#sieve_default =
sieve_before = /var/vmail/sieve/dovecot.sieve
\#sieve_after =
\# The maximum number of redirect actions that can be performed during a
\# single script execution.
\# The meaning of 0 differs based on your version. For pigeonhole-0.3.0 and
\# beyond this means that redirect is prohibited. For older versions,
\# however, this means that the number of redirects is unlimited.
sieve_max_redirects = 30
\# Reference: http://wiki2.dovecot.org/Plugins/MailboxAlias
mailbox_alias_old = Sent
mailbox_alias_new = Sent Messages
mailbox_alias_old2 = Sent
mailbox_alias_new2 = Sent Items
\# Events to log. `autoexpunge` is included in `expunge`
\# Defined in https://github.com/dovecot/core/blob/master/src/plugins/mail-log/mail-log-plugin.c
mail_log_events = delete undelete expunge mailbox_delete mailbox_rename
mail_log_fields = uid box msgid size from subject }
service quota-warning {
executable = script /usr/local/bin/dovecot-quota-warning.sh
unix_listener quota-warning {
user = vmail
group = vmail
mode = 0660
} }
service dict {
unix_listener dict {
mode = 0660
user = vmail
group = vmail
} }
dict {
#expire = db:/var/lib/dovecot/expire/expire.db
quotadict = mysql:/etc/dovecot/dovecot-used-quota.conf
acl = mysql:/etc/dovecot/dovecot-share-folder.conf }
protocol lda {
# Reference: http://wiki2.dovecot.org/LDA
mail_plugins = $mail_plugins sieve
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
postmaster_address = root
\# Log file path if we use internal log system
\#log_path = /var/log/dovecot/sieve.log }
protocol lmtp {
# Log file path if we use internal log system
#log_path = /var/log/dovecot/lmtp.log
\# Plugins
mail_plugins = quota sieve
postmaster_address = postmaster
\# Address extension delivery
lmtp_save_to_detail_mailbox = yes
recipient_delimiter = + }
protocol imap {
mail_plugins = $mail_plugins imap_quota imap_acl
imap_client_workarounds = tb-extra-mailbox-sep
\# Maximum number of IMAP connections allowed for a user from each IP address.
\# NOTE: The username is compared case-sensitively.
\# Default is 10.
\# Increase it to avoid issue like below:
\# "Maximum number of concurrent IMAP connections exceeded"
mail_max_userip_connections = 30 }
protocol pop3 {
mail_plugins = $mail_plugins
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
pop3_uidl_format = %08Xu%08Xv
\# Maximum number of IMAP connections allowed for a user from each IP address.
\# NOTE: The username is compared case-sensitively.
\# Default is 10.
mail_max_userip_connections = 30
\# POP3 logout format string:
\# %i - total number of bytes read from client
\# %o - total number of bytes sent to client
\# %t - number of TOP commands
\# %p - number of bytes sent to client as a result of TOP command
\# %r - number of RETR commands
\# %b - number of bytes sent to client as a result of RETR command
\# %d - number of deleted messages
\# %m - number of messages (before deletion)
\# %s - mailbox size in bytes (before deletion)
\# Default format doesn't have 'in=%i, out=%o'.
\#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s, in=%i, out=%o }
# Login processes. Refer to Dovecot wiki for more details: #
http://wiki2.dovecot.org/LoginProcess service imap-login {
#inet_listener imap {
# port = 143
#}
#inet_listener imaps {
# port = 993
# ssl = yes
#}
service_count = 1
\# To avoid startup latency for new client connections, set process_min_avail
\# to higher than zero. That many idling processes are always kept around
\# waiting for new connections.
\#process_min_avail = 0
\# number of simultaneous IMAP connections
process_limit = 500
\# vsz_limit should be fine at its default 64MB value
\#vsz_limit = 64M }
service pop3-login {
#inet_listener pop3 {
# port = 110
#}
#inet_listener pop3s {
# port = 995
# ssl = yes
#}
service_count = 1
\# number of simultaneous POP3 connections
\#process_limit = 500 }
service managesieve-login {
inet_listener sieve {
# Listen on localhost (ipv4)
address = 127.0.0.1
port = 4190
} }
namespace {
type = private
separator = /
prefix =
inbox = yes
\# Refer to document for more details about alias mailbox:
\# http://wiki2.dovecot.org/MailboxSettings
\#
\# Sent
mailbox Sent {
auto = subscribe
special_use = \Sent
}
mailbox "Sent Messages" {
auto = no
special_use = \Sent
}
mailbox "Sent Items" {
auto = no
special_use = \Sent
}
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
\# Trash
mailbox Trash {
auto = subscribe
special_use = \Trash
}
mailbox "Deleted Messages" {
auto = no
special_use = \Trash
}
\# Junk
mailbox Junk {
auto = subscribe
special_use = \Junk
}
mailbox Spam {
auto = no
special_use = \Junk
}
mailbox "Junk E-mail" {
auto = no
special_use = \Junk
}
\# Archive
mailbox Archive {
auto = no
special_use = \Archive
}
mailbox Archives {
auto = no
special_use = \Archive
} }
namespace {
type = shared
separator = /
prefix = Shared/%%u/
location = maildir:%%Lh/Maildir/:INDEX=%%Lh/Maildir/Shared/%%Ld/%%Ln
\# this namespace should handle its own subscriptions or not.
subscriptions = yes
list = children }
# Public mailboxes. # Refer to Dovecot wiki page for more details:
# http://wiki2.dovecot.org/SharedMailboxes/Public #namespace { #
type = public # separator = / # prefix = Public/ #
location =
maildir:/var/vmail/public:CONTROL=%Lh/Maildir/public:INDEXPVT=%Lh/Maildir/public
# # # Allow users to subscribe to the public folders. #
subscriptions = yes #}
It looks like the ClamAV hangs and times out after 5 minutes. Would that explain things? I find it hard to read your configurations.

Operating Micropython-running WeMos D1 mini (ESP8266) pins with HTTP requests

What I am trying to ultimately achieve is to control my garage door opener with a relay connected to a WeMos D1 Mini, connected to my home WiFi. I am using the openGarageDoor() function. Everything works fine with serial connection.
I have been trying to run HTTP server on a WeMos D1 Mini with this script.
customertagsAction() -- try:
import usocket as socket
except:
import socket
CONTENT = b"""\
HTTP/1.0 200 OK
Hello #%d from MicroPython!
"""
def main(micropython_optimize=False):
s = socket.socket()
# Binding to all interfaces - server will be accessible to other hosts!
ai = socket.getaddrinfo("0.0.0.0", 8080)
print("Bind address info:", ai)
addr = ai[0][-1]
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(5)
print("Listening, connect your browser to http://<this_host>:8080/")
counter = 0
while True:
res = s.accept()
client_sock = res[0]
client_addr = res[1]
print("Client address:", client_addr)
print("Client socket:", client_sock)
if not micropython_optimize:
# To read line-oriented protocol (like HTTP) from a socket (and
# avoid short read problem), it must be wrapped in a stream (aka
# file-like) object. That's how you do it in CPython:
client_stream = client_sock.makefile("rwb")
else:
# .. but MicroPython socket objects support stream interface
# directly, so calling .makefile() method is not required. If
# you develop application which will run only on MicroPython,
# especially on a resource-constrained embedded device, you
# may take this shortcut to save resources.
client_stream = client_sock
print("Request:")
req = client_stream.readline()
print(req)
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
print(h)
client_stream.write(CONTENT % counter)
client_stream.close()
if not micropython_optimize:
client_sock.close()
counter += 1
print()
main()
The requests are received properly and the GET variables are shown on the print(). The best i have been able to do is
req = client_stream.readline()
print(req)
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
print(h)
client_stream.write(CONTENT % counter)
//my function here:
if 'opengaragedoor=1' in req:
openGarageDoor()
client_stream.close()
I don't know how to parse the request properly. I only have come up with this dirty solution. This probably causes a timeout on the requesting system, as Postman or such needs to wait for the function to run through.

wireshark count packets by port

I have a very large trace file and am trying to use Wireshark to determine which dest port has the most packets sent to it. Is there a way to get counts of packets sent to particular ports? Or to sort by number of packets sent a port?
You can write a simple wireshark listener in lua.
local tap
local ports = {}
local function packet(pinfo, tvb, userdata)
-- store number of packets per each port
local port = pinfo.dst_port
ports[port] = (ports[port] or 0) + 1
end
local function draw(userdata)
local maxi,maxv = 0,0
-- print all gathered statictics and find max
for i,v in pairs(ports) do
print(i .. ":", v)
if maxv < v then
maxi,maxv = i,v
end
end
print ("Max:", maxi, maxv)
end
local function reset(userdata)
ports = {}
end
local function show_ports()
tap = Listener.new()
tap.packet = packet
tap.draw = draw
tap.reset = reset
end
register_stat_cmd_arg('ports', show_ports)
Try it:
tshark -X lua_script:ports.lua -z ports -r in.pcap

How to find the largest UDP packet I can send without fragmenting?

I need to know what the largest UDP packet I can send to another computer is without fragmentation.
This size is commonly known as the MTU (Maximum Transmission Unit). Supposedly, between 2 computers, will be many routers and modems that may have different MTUs.
I read that the TCP implementation in windows automatically finds the maximum MTU in a path.
I was also experimenting, and I found out that the maximum MTU from my computer to a server was 57712 bytes+header. Anything above that was discarded. My computer is on a LAN, isn't the MTU supposed to be around 1500 bytes?
The following doesn't answer your question directly but you might find it interesting; it says that IP packets can be disassembled/reassembled, and therefore bigger than limit on the underling media (e.g. 1500-byte Ethernet): Resolve IP Fragmentation, MTU, MSS, and PMTUD Issues with GRE and IPSEC
More on this topic:
Re: UDP fragmentation says you should use ICMP instead of UDP to discover MTU
Path MTU Discovery says that a TCP connection might include implicit MTU negotiation via ICMP
I don't know about generating ICMP via an API on Windows: at one time such an API was proposed, and was controversial because people argued that would make it easy to write software that implements denial-of-service functionality by generating a flood of ICMP messages.
No, it looks like it is implemented: see for example Winsock Programmer's FAQ Examples: Ping: Raw Sockets Method.
So, to discover MTU, generate ping packets with the 'do not fragment' flag.
Maybe there's an easier API than this, I don't know; but I hope I've given you to understand the underlying protocol[s].
In addition to all the previous answers, quoting the classic:
IPv4 and IPv6 define minimum reassembly buffer size, the minimum datagram size that we are guaranteed any implementation must support. For IPv4, this is 576 bytes. IPv6 raises this to 1,280 bytes.
This pretty much means that you want to limit your datagram size to under 576 if you work over public internet and you control only one side of the exchange - that's what most of the standard UDP-based protocols do.
Also note that PMTU is a dynamic property of the path. This is one of the things TCP deals with for you. Unless you are ready to re-implement lots of sequencing, timing, and retransmission logic, use TCP for any critical networking. Benchmark, test, profile, i.e. prove that TCP is your bottleneck, only then consider UDP.
This is an interesting topic for me. Perhaps some practical results might be of interest when delivering chunky UDP data around the real world internet via UDP, and with a transmission rate of 1 packet a second, data continues to turn up with minimal packet loss up to about 2K. Over this and you start running into issues, but regularly we delivered 1600+ bytes packets without distress - this is over GPRS mobile networks as well as WAN world wide. At ~1K assuming the signal is stable (its not!) you get low packet loss.
Interestingly its not the odd packet, but often a squall of packets for a few seconds - which presumably is why VoIP calls just collapse occasionally.
Your own MTU is available in the registry, but the MTU in practice is going to the smallest MTU in the path between your machine and the destination. Its both variable and can only be determined empirically. There are a number of RFCs showing how to determine it.
LAN's can internally have very large MTU values, since the network hardware is typically homogeneous or at least centrally administrated.
For UDP applications you must handle end-to-end MTU yourself if you want to avoid IP fragmentation or dropped packets. The recommended approach for any application is to do your best to use PMTU to pick your maximum datagram, or send datagrams < minimum PMTU
https://www.rfc-editor.org/rfc/rfc5405#section-3.2
Unicast UDP Usage Guidelines for Application Designers "SHOULD NOT send datagrams that exceed the PMTU, SHOULD discover PMTU or send datagrams < minimum PMTU
Windows appears to settings and access to PMTU information via it's basic socket options interface:
You can make sure PMTU discover is on via IP_MTU_DISCOVER, and you can read the MTU via IP_MTU.
https://learn.microsoft.com/en-us/windows/desktop/winsock/ipproto-ip-socket-options
Here's a bit of Windows PowerShell that I wrote to check for Path MTU issues. (The general technique is not too hard to implement in other programming languages.) A lot of firewalls and routers are configured to drop all ICMP by people who don't know any better. Path MTU Discovery depends on being able to receive an ICMP Destination Unreachable message with Fragementation Needed set in response to sending a packet with Don't Fragment set. The Resolve IPv4 Fragmentation, MTU, MSS, and PMTUD Issues with GRE and IPsec actually does a really good job of explaining how discovery works.
function Test-IPAddressOrName($ipAddressOrName)
{
$ipaddress = $null
$isValidIPAddressOrName = [ipaddress]::TryParse($ipAddressOrName, [ref] $ipaddress)
if ($isValidIPAddressOrName -eq $false)
{
$hasResolveDnsCommand = $null -ne (Get-Command Resolve-DnsName -ErrorAction SilentlyContinue)
if ($hasResolveDnsCommand -eq $true)
{
$dnsResult = Resolve-DnsName -DnsOnly -Name $ipAddressOrName -ErrorAction SilentlyContinue
$isValidIPAddressOrName = $null -ne $dnsResult
}
}
return $isValidIPAddressOrName
}
function Get-NameAndIPAddress($ipAddressOrName)
{
$hasResolveDnsCommand = $null -ne (Get-Command Resolve-DnsName -ErrorAction SilentlyContinue)
$ipAddress = $null
$validIPAddress = [ipaddress]::TryParse($ipAddressOrName, [ref] $ipAddress)
$nameAndIp = [PSCustomObject] #{ 'Name' = $null; 'IPAddress' = $null }
if ($validIPAddress -eq $false)
{
if ($hasResolveDnsCommand -eq $true)
{
$dnsResult = Resolve-DnsName -DnsOnly $ipAddressOrName -Type A -ErrorAction SilentlyContinue
if ($null -ne $dnsResult -and $dnsResult.QueryType -eq 'A')
{
$nameAndIp.Name = $dnsResult.Name
$nameAndIp.IPAddress = $dnsResult.IPAddress
}
else
{
Write-Error "The name $($ipAddressOrName) could not be resolved."
$nameAndIp = $null
}
}
else
{
Write-Warning "Resolve-DnsName not present. DNS resolution check skipped."
}
}
else
{
$nameAndIp.IPAddress = $ipAddress
if ($hasResolveDnsCommand -eq $true)
{
$dnsResult = Resolve-DnsName -DnsOnly $ipAddress -Type PTR -ErrorAction SilentlyContinue
if ($null -ne $dnsResult -and $dnsResult.QueryType -eq 'PTR')
{
$nameAndIp.Name = $dnsResult.NameHost
}
}
}
return $nameAndIp
}
<#
.Synopsis
Performs a series of pings (ICMP echo requests) with Don't Fragment specified to discover the path MTU (Maximum Transmission Unit).
.Description
Performs a series of pings with Don't Fragment specified to discover the path MTU (Maximum Transmission Unit). An ICMP echo request
is sent with a random payload with a payload length specified by the PayloadBytesMinimun. ICMP echo requests of increasing size are
sent until a ping response status other than Success is received. If the response status is PackeTooBig, the last successful packet
length is returned as a reliable MTU; otherwise, if the respone status is TimedOut, the same size packet is retried up to the number
of retries specified. If all of the retries have been exhausted with a response status of TimedOut, the last successful packet
length is returned as the assumed MTU.
.Parameter UseDefaultGateway
If UseDefaultGateway is specified the default gateway reported by the network interface is used as the destination host.
.Parameter DestinationHost
The IP Address or valid fully qualified DNS name of the destination host.
.Parameter InitialTimeout
The number of milliseconds to wait for an ICMP echo reply. Internally, this is doubled each time a retry occurs.
.Parameter Retries
The number of times to try the ping in the event that no reply is recieved before the timeout.
.Parameter PayloadBytesMinimum
The minimum number of bytes in the payload to use. The minimum MTU for IPv4 is 68 bytes; however, in practice, it's extremely rare
to see an MTU size less than 576 bytes so the default value is 548 bytes (576 bytes total packet size minus an ICMP header of 28
bytes).
.Parameter PayloadBytesMaximum
The maximum number of bytes in the payload to use. An IPv4 MTU for jumbo frames is 9000 bytes. The default value is 8973 bytes (9001
bytes total packet size, which is 1 byte larger than the maximum IPv4 MTU for a jumbo frame, minus an ICMP header of 28 bytes).
.Example
Discover-PathMTU -UseDefaultGateway
.Example
Discover-PathMTU -DestinationHost '192.168.1.1'
.Example
Discover-PathMTU -DestinationHost 'www.google.com'
#>
function Discover-PathMtu
{
[CmdletBinding(SupportsShouldProcess = $false)]
param
(
[Parameter(Mandatory = $true, ParameterSetName = 'DefaultGateway')]
[switch] $UseDefaultGateway,
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = 'IPAddressOrName')]
[ValidateScript({ Test-IPAddressOrName $_ })]
[string] $DestinationHost,
[Parameter(ParameterSetName = 'IPAddressOrName')]
[Parameter(ParameterSetName = 'DefaultGateway')]
[int] $InitialTimeout = 3000,
[Parameter(ParameterSetName = 'IPAddressOrName')]
[Parameter(ParameterSetName = 'DefaultGateway')]
[int] $Retries = 3,
[Parameter(ParameterSetName = 'IPAddressOrName')]
[Parameter(ParameterSetName = 'DefaultGateway')]
$PayloadBytesMinimum = 548,
[Parameter(ParameterSetName = 'IPAddressOrName')]
[Parameter(ParameterSetName = 'DefaultGateway')]
$PayloadBytesMaximum = 8973
)
begin
{
$ipConfiguration = Get-NetIPConfiguration -Detailed | ?{ $_.NetProfile.Ipv4Connectivity -eq 'Internet' -and $_.NetAdapter.Status -eq 'Up' } | Sort { $_.IPv4DefaultGateway.InterfaceMetric } | Select -First 1
$gatewayIPAddress = $ipConfiguration.IPv4DefaultGateway.NextHop
$pingOptions = New-Object System.Net.NetworkInformation.PingOptions
$pingOptions.DontFragment = $true
$pinger = New-Object System.Net.NetworkInformation.Ping
$rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
}
process
{
$pingIpAddress = $null
if ($UseDefaultGateway -eq $true)
{
$DestinationHost = $gatewayIPAddress
}
$nameAndIP = Get-NameAndIPAddress $DestinationHost
if ($null -ne $nameAndIP)
{
Write-Host "Performing Path MTU discovery for $($nameAndIP.Name) $($nameAndIP.IPAddress)..."
$pingReply = $null
$payloadLength = $PayloadBytesMinimum
$workingPingTimeout = $InitialTimeout
do
{
$payloadLength++
# Use a random payload to prevent compression in the path from potentially causing a false MTU report.
[byte[]] $payloadBuffer = (,0x00 * $payloadLength)
$rng.GetBytes($payloadBuffer)
$pingCount = 1
do
{
$pingReply = $pinger.Send($nameAndIP.IPAddress, $workingPingTimeout, $payloadBuffer, $pingOptions)
if ($pingReply.Status -notin 'Success', 'PacketTooBig', 'TimedOut')
{
Write-Warning "An unexpected ping reply status, $($pingReply.Status), was received in $($pingReply.RoundtripTime) milliseconds on attempt $($pingCount)."
}
elseif ($pingReply.Status -eq 'TimedOut')
{
Write-Warning "The ping request timed out while testing a packet of size $($payloadLength + 28) using a timeout value of $($workingPingTimeout) milliseconds on attempt $($pingCount)."
$workingPingTimeout = $workingPingTimeout * 2
}
else
{
Write-Verbose "Testing packet of size $($payloadLength + 28). The reply was $($pingReply.Status) and was received in $($pingReply.RoundtripTime) milliseconds on attempt $($pingCount)."
$workingPingTimeout = $InitialTimeout
}
Sleep -Milliseconds 10
$pingCount++
} while ($pingReply.Status -eq 'TimedOut' -and $pingCount -le $Retries)
} while ($payloadLength -lt $PayloadBytesMaximum -and $pingReply -ne $null -and $pingReply.Status -eq 'Success')
if ($pingReply.Status -eq 'PacketTooBig')
{
Write-Host "Reported IPv4 MTU is $($ipConfiguration.NetIPv4Interface.NlMtu). The discovered IPv4 MTU is $($payloadLength + 27)."
}
elseif ($pingReply.Status -eq 'TimedOut')
{
Write-Host "Reported IPv4 MTU is $($ipConfiguration.NetIPv4Interface.NlMtu). The discovered IPv4 MTU is $($payloadLength + 27), but may not be reliable because the packet appears to have been discarded."
}
else
{
Write-Host "Reported IPv4 MTU is $($ipConfiguration.NetIPv4Interface.NlMtu). The discovered IPv4 MTU is $($payloadLength + 27), but may not be reliable, due to an unexpected ping reply status."
}
return $payloadLength + 27
}
else
{
Write-Error "The name $($DestinationHost) could not be resolved. No Path MTU discovery will be performed."
}
}
end
{
if ($null -ne $pinger)
{
$pinger.Dispose()
}
if ($null -ne $rng)
{
$rng.Dispose()
}
}
}

Resources