As the title says I want to programmatically check if a DNS response for a domain are protected with DNSSEC.
How could I do this?
It would be great, if there is a pythonic solution for this.
UPDATE:
changed request to response, sorry for the confusion
Using a DNS resolver (e.g. dnspython), you can query the domain for its DNSKEY RRset and turn on the DO (dnssec OK) query flag. If the query succeeds, the answer will have the AD (authenticated data) flag set and will contain the RRSIG signatures for the zone (if it is signed).
Update: a basic example using dnspython
import dns.name
import dns.query
import dns.dnssec
import dns.message
import dns.resolver
import dns.rdatatype
# get nameservers for target domain
response = dns.resolver.query('example.com.',dns.rdatatype.NS)
# we'll use the first nameserver in this example
nsname = response.rrset[0].to_text() # name
response = dns.resolver.query(nsname,dns.rdatatype.A)
nsaddr = response.rrset[0].to_text() # IPv4
# get DNSKEY for zone
request = dns.message.make_query('example.com.',
dns.rdatatype.DNSKEY,
want_dnssec=True)
# send the query
response = dns.query.udp(request,nsaddr)
if response.rcode() != 0:
# HANDLE QUERY FAILED (SERVER ERROR OR NO DNSKEY RECORD)
# answer should contain two RRSET: DNSKEY and RRSIG(DNSKEY)
answer = response.answer
if len(answer) != 2:
# SOMETHING WENT WRONG
# the DNSKEY should be self signed, validate it
name = dns.name.from_text('example.com.')
try:
dns.dnssec.validate(answer[0],answer[1],{name:answer[0]})
except dns.dnssec.ValidationFailure:
# BE SUSPICIOUS
else:
# WE'RE GOOD, THERE'S A VALID DNSSEC SELF-SIGNED KEY FOR example.com
To see if a particular request is protected, look at the DO flag in the request packet. Whatever language and library you use to interface to DNS should have an accessor for it (it may be called something else, like "dnssec").
The first answer is correct but incomplete if you want to know if a certain zone is protected. The described procedure will tell you if the zone's own data is signed. In order to check that the delegation to the zone is protected, you need to ask the parent zone's name servers for a (correctly signed) DS record for the zone you're interested in.
Related
I have a server list:
hosts=['server1','server2','server3','server4']
there are server 4 monitoring tools accessed by api calls. these monitoring env urls basically the same except for each env has unique id which is part of the url. These servers can be on any of the 4 monitoring tools. I need to find out which url these servers belong to.
for example, these are the monitoring tools urls:
production_env="https://example.com/e/envid123"
dev_env="https://example.com/e/envid678"
test_env="https://example.com/e/envid567"
uat_env="https://example.com/e/envid1000"
given the server name, I need to find out which env they belong to.
given a server name, for example "server1",
api url would become https://example.com/e/envid123&serverName="server1", this url will give whether server1 exists in production_env or not. I need to check each env url until I find the given server.
I am trying something like this:
envId=['envid123','envid678','envid567','envid1000']
for server in hosts:
for id in envId:
url="https://example.com/e/"+id+&serverName=server
resp=request.get(url)
Any ideas how could do this the best way?
You need quotes around &serverName= to concatenate them. But it's simpler to use a formatting method, such as f-strings.
To find the desired URL, use resp.json to get the decoded JSON, and check the value of the appropriate dictionary element.
found = False
for server in hosts:
for id in envId:
url = f"https://example.com/e/{id}&serverName={server}"
resp = request.get(url)
if resp.json['totalCount'] > 0:
found = True
print(f"Success at host = {server} id = {id}")
break
if found:
break
else:
print("No server found")
I am trying to redirect one page to another by using mitmproxy and Python. I can run my inline script together with mitmproxy without issues, but I am stuck when it comes to changing the URL to another URL. Like if I went to google.com it would redirect to stackoverflow.com
def response(context, flow):
print("DEBUG")
if flow.request.url.startswith("http://google.com/"):
print("It does contain it")
flow.request.url = "http://stackoverflow/"
This should in theory work. I see http://google.com/ in the GUI of mitmproxy (as GET) but the print("It does contain it") never gets fired.
When I try to just put flow.request.url = "http://stackoverflow.com" right under the print("DEBUG") it won't work neither.
What am I doing wrong? I have also tried if "google.com" in flow.request.url to check if the URL contains google.com but that won't work either.
Thanks
The following mitmproxy script will
Redirect requesto from mydomain.com to newsite.mydomain.com
Change the request method path (supposed to be something like /getjson? to a new one `/getxml
Change the destination host scheme
Change the destination server port
Overwrite the request header Host to pretend to be the origi
import mitmproxy
from mitmproxy.models import HTTPResponse
from netlib.http import Headers
def request(flow):
if flow.request.pretty_host.endswith("mydomain.com"):
mitmproxy.ctx.log( flow.request.path )
method = flow.request.path.split('/')[3].split('?')[0]
flow.request.host = "newsite.mydomain.com"
flow.request.port = 8181
flow.request.scheme = 'http'
if method == 'getjson':
flow.request.path=flow.request.path.replace(method,"getxml")
flow.request.headers["Host"] = "newsite.mydomain.com"
You can set .url attribute, which will update the underlying attributes. Looking at your code, your problem is that you change the URL in the response hook, after the request has been done. You need to change the URL in the request hook, so that the change is applied before requesting resources from the upstream server.
Setting the url attribute will not help you, as it is merely constructed from underlying data. [EDIT: I was wrong, see Maximilian’s answer. The rest of my answer should still work, though.]
Depending on what exactly you want to accomplish, there are two options.
(1) You can send an actual HTTP redirection response to the client. Assuming that the client understands HTTP redirections, it will submit a new request to the URL you give it.
from mitmproxy.models import HTTPResponse
from netlib.http import Headers
def request(context, flow):
if flow.request.host == 'google.com':
flow.reply(HTTPResponse('HTTP/1.1', 302, 'Found',
Headers(Location='http://stackoverflow.com/',
Content_Length='0'),
b''))
(2) You can silently route the same request to a different host. The client will not see this, it will assume that it’s still talking to google.com.
def request(context, flow):
if flow.request.url == 'http://google.com/accounts/':
flow.request.host = 'stackoverflow.com'
flow.request.path = '/users/'
These snippets were adapted from an example found in mitmproxy’s own GitHub repo. There are many more examples there.
For some reason, I can’t seem to make these snippets work for Firefox when used with TLS (https://), but maybe you don’t need that.
I'm connecting to the Twitter Streaming API and am setting up the OAuth handshake. I need to request a token and send a callback_url as a params dictionary along with post request.
I've hardcoded in the url for development (http://localhost:8000/oauth) but when I deploy this will change. I want to set up something that will find the host and port and set a reference it. Ideally, looking like "http://%s/oauth" % (domain_name)
I've tried using both the os and socket modules, and code is below:
class OAuth:
def request_oauthtoken(self):
name = socket.gethostname()
ip = socket.gethostbyname(name)
domain = socket.gethostbyaddr(ip) # Sequence attempts to find the current domain name. This will add expandability to the calling the API, as opposed to hard coding it in. It's not returning what I'm expecting
payload = { 'oauth_callback': 'http://localhost:8000/oauth' }
print(domain)
return payload
domain returns ('justins-mbp-2.local.tld', ['145.15.168.192.in-addr.arpa'], ['192.168.15.145'])
name returns the first element of the tuple above and ip returns the last item of the tuple unwrapped from the collection.
I'm looking for a return value of localhost or localhost:8000. I can work with either one.
call request.build_absolute_uri(), then extract the domain.
docs:
HttpRequest.build_absolute_uri(location) Returns the absolute URI form
of location. If no location is provided, the location will be set to
request.get_full_path().
If the location is already an absolute URI, it will not be altered.
Otherwise the absolute URI is built using the server variables
available in this request.
Example: "http://example.com/music/bands/the_beatles/?print=true"
I am writing a piece of code that uses authentication from ldap server. Currently my code only lets the user DN and the pwd to be presented for login.
Username: CN=mynane,CN=Users,DC=example,DC=com
Pwd : XXXX
Now what is want to do is allow the username in the format
Username: myname#example.com
Pwd: xxxx
I can bind to the server using the credentials in the format "myname#example.com", but my code needs the group of the 'myname' as well for authentication. For that I need to find out the DN from "myname#example.com" so that I can extract the group 'myname' belongs to.
So my question is how can I find out the DN from format "myname#example.com"
How is it done?
Thanks
If you want to query dn by email address, you might try the following codes.
ldap = "SELECT distinguishedName From 'LDAP://DC=example,DC=com' WHERE mail = '{}'"
mail = 'myname#example.com'
import win32com.client
c = win32com.client.Dispatch('ADODB.Connection')
c.Open('Provider=ADsDSOObject')
rs,rc = c.Execute(ldap.format(mail))
while not rs.EOF:
for e in rs.fields:
print('{}: {}'.format(e.Name, e.Value))
rs.MoveNext()
you will have to fetch the user whose 'userPrincipalName'='myname#example.com' or 'samAccountName'='myname'
You have to do two things:
Find the right subtree for the DNS domain example.com (usually from the Configuration subtree), if you only have one domain, its easier, simply ignore the part after the #.
Look inside that subtree for the sAMAccountName=myname, as it is unique inside the domain.
Those names often look like UPNs but aren't. In fact they are usually just the sAMAccountName attached to the DNS domain name.
Type not found: '(ArrayOfint, http://schemas.microsoft.com/2003/10/Serialization/Arrays, )'
is what suds resolver raises.
In ...2003/10/Serialization/Arrays ArrayOfInt is defined, so I guess linux' case sensitivity is the problem.
Any Idea how I can get around that?
from suds.client import Client
c = Client("https://developer-api.affili.net/V2.0/Logon.svc?wsdl")
used to return
Type not found: '(ArrayOfint, http://schemas.microsoft.com/2003/10/Serialization/Arrays, )'
now since a few days I don't even get there anymore but instead I get a
TypeNotFound: Type not found: '(Logon, http://affilinet.framework.webservices/types, )'
Sounds like you have a broken WSDL. This is where you'll need to use the ImportDoctor provided by SUDS. You need use this to help the Client constructor use the ArrayOfint type found at http://schemas.microsoft.com/2003/10/Serialization/Arrays.
I have done this in the past with other services but without seeing your WSDL or your code, this is only my best guess as to how you may fix it because I can't test it myself:
from suds.client import Client
from suds.xsd.doctor import Import, ImportDoctor
# Obviously I made this up
wsdl_url = 'http://whatever/path/to/wsdl'
# Fix missing types with ImportDoctor
schema_url = 'http://schemas.microsoft.com/2003/10/Serialization/Arrays'
schema_import = Import(schema_url)
schema_doctor = ImportDoctor(schema_import)
# Pass doctor to Client
client = Client(url=wsdl_url, doctor=schema_doctor)
One thing worth noting is that the URL http://schemas.microsoft.com/2003/10/Serialization/Arrays is not even valid (it returns a 404), so I am really not sure that is the right URL. Although I am confident that I am at least steering you in the right direction.
Edit in response to your recent comment (2010-10-05):
Using the URL you provided of https://developer-api.affili.net/V2.0/Logon.svc?wsdl I was able to successfully create a client. I had to use an ImportDoctor because it raised the following error:
TypeNotFound: Type not found: '(Logon, http://affilinet.framework.webservices/types, )'
So I used the following code and was able to get a successful client object:
from suds.client import Client
from suds.xsd.doctor import Import, ImportDoctor
wsdl_url = 'https://developer-api.affili.net/V2.0/Logon.svc?wsdl'
schema_url = 'http://affilinet.framework.webservices/types'
schema_import = Import(schema_url)
schema_doctor = ImportDoctor(schema_import)
client = Client(url=wsdl_url, doctor=schema_doctor)
Printing the client object displays this:
Suds ( https://fedorahosted.org/suds/ ) version: 0.3.9 GA build: R659-20100219
Service ( Authentication ) tns="http://affilinet.framework.webservices/Svc"
Prefixes (5)
ns0 = "http://affilinet.framework.webservices/types"
ns1 = "http://schemas.datacontract.org/2004/07/Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF"
ns2 = "http://schemas.microsoft.com/2003/10/Serialization/"
ns3 = "http://schemas.microsoft.com/2003/10/Serialization/Arrays"
ns4 = "http://www.microsoft.com/practices/EnterpriseLibrary/2007/01/wcf/validation"
Ports (1):
(DefaultEndpointLogon)
Methods (2):
GetIdentifierExpiration(xs:string CredentialToken, )
Logon(xs:string Username, xs:string Password, ns0:WebServiceTypes WebServiceType, ns0:TokenDeveloperDetails DeveloperSettings, ns0:TokenApplicationDetails ApplicationSettings, )
Types (12):
ns3:ArrayOfKeyValueOfstringstring
ns1:ArrayOfValidationDetail
ns0:Logon
ns0:TokenApplicationDetails
ns0:TokenDeveloperDetails
ns1:ValidationDetail
ns4:ValidationFault
ns0:WebServiceTypes
ns0:affilinetWebserviceFault
ns2:char
ns2:duration
ns2:guid
Before you can use client.service.Logon() you're going to have to satisfy the type signature required by that method. You'll have to create various type objects using client.factory.create() (e.g. client.factory.create('ns0:WebServiceTypes')) and pass those objects along with your username/password.